一、xue的生命周期是什么
vue每个组件都是独立的,,每个组件都有一个属于他的生命周期,从一个组件创建、数据初始化、挂载、更新、到销毁,这就剩一个组件所谓的生命周期,并且所有的生命周期钩子的this上下文将自动绑定至实例中。
vw的换算
vw是根据浏览器视口宽度来计算,1vw就是1%,以苹果6为例,我们就可以在顶端设置26.66667vw去进行换算。
rem的换算
rem是根据你根目录的字体大小来进行计算,如果根目录大小时16px,那么他的1rem就是16px,如果根目录是10px,那么1rem就是10px,但是在谷歌浏览器中,强制最小字体为12px,那么如果按照根目录10px来算的话,这里就会出现偏差,,可以将10px给他改成100px,方便计算
强缓存与协商缓存
强缓存:就是在本地缓存中查看是否有复合请资源的数据,如果有则使用本地的缓存资源,如果没有就像服务器发起请求。
协商缓存:在请求资源时,将用户本地的etag携带过去,然后服务端和资源做对比,如果资源没更改就,读取本地储存,如果资源有更改,则返回最新资源
在shouldComponentUpdate可以使用setState吗?
禁止在 shouldComponentUpdate 和 componentWillUpdate中调用setState,这会造成循环调用,直至耗光浏览器内存后崩溃。不可以
- shouldComponentUpdate` 或者 componentWillUpdate里调用 setState 会再次触发这两个函数,然后在两个函数又触发了 setState,然后再次触发这两个函数。从而死循环。
js怎么判断对象
1、tostring (object.prototype.tostring.call(obj)
2、constructor obj.constrctor===object
3、instanceof obj instanceof object
4、typeog typeof obj === Object
// 根据typeof判断对象也不太准确
表达式 返回值
typeof undefined 'undefined'
typeof null 'object'
typeof true 'boolean'
typeof 123 'number'
typeof "abc" 'string'
typeof function() {} 'function'
typeof {} 'object'
typeof [] 'object'
js怎么判断是否为数组
1、instanceof arr onstanceof array
2、-popto- arr ._ proto _ === array.prototype
3、constructor arr.constructor === array
4、object.prototype.tostring object.prototype.tostring.call(arr) === [object array]
5、array.isarray(arr)
项目打包上线后出现空白怎么解决
在你还没打包之前找到package.json这个文件,添加一行"homepage":"./"就可以了。
二、vue生命周期有哪些
1、(比否可瑞A特):在实例初始化之后,进行数据侦听和事件/侦听器的配置之前同步调用
2、Created(可瑞A特)在实例创建完成后被立即同步调用,在这一步中,实例已完成对选项的处理,意味着以下内容已被配置完毕:数据侦听,计算属性、方法、事件/侦听器的回调函数,然而,挂载阶段还没开始,且$el property目前尚不可用
3、beforeMoun比否盲特)在挂载开始之前被调用:相关的render函数首次被调用
4、mounted(盲腾的)实例被挂载后调用,这时el被新创建的vm.el也在文档内
注意mounted不会保证所有的子组件也都被挂载完成,如果你希望等到整个视图都渲染完毕在执行某些操作,可以在mounted内部使用vm.$nextTick
5、beforeUpdate(比否啊铺得特)早数据发生改变后,DOM被更新之前被调用,这里适合在现有DOM将DOM将要在被更新之前访问他,比如移除手动添加的事件监听器等,
6、updated (啊铺得特)在数据更改导致的虚拟DOM重新渲染和更新完毕之后被调用,当这个钩子被调用时,组件DOM已经更新,所以你现在可以执行依赖于DOM的操作,然而在大多数情况下,你应该避免在此期间更改状态,如果要更改相应的状态,通常最好使用计算属性或者watcher取而代之
7、activated(啊特为得)被keep-alive缓存的组件激活时调用
8、deactivated(d啊特为得)被keep-alive缓存的组件失活时调用
9、beforeDestroy(比否迪斯jo瑞)实例销毁之前调用,在这一步,实例仍然完成可用
10、destroyed(迪斯jo瑞的)实例销毁后调用,对应Vue实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁
11、errorCaptured(a若卡不缺特)在捕获一个来自后代组件的错误时被调用,此钩子会受到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串,此钩子可以返回false以阻止该错误继续向上传播。
三、vue生命周期的在项目中的执行顺序
1、beforeCreate(比否可瑞A特)
2、Create(可瑞A特)
3、beforeMount(比否盲特)
4、mounted(盲腾得)
5、beforeDestroy(比否迪斯jo瑞)
6、destroyed(迪斯jo瑞的)
四、actived(啊特为得)生命周期在哪个组件中调用?
在keep -alive组件中调用,
五、父子子件的加载顺序
父组件beforeCreated(比否可瑞A特)->父组件beforeMounted(比否盲腾特)->子组件beforeCreated(比否可瑞A特)
->子组件created(可瑞A特)->子组件beforeMounted(比否盲腾特)--.子组件mounted->父组件mounted
六、vue路由传参的方式
1、直接调用$router.push实现携带参数的跳转(通过拼接地址栏参数)
2、通过路由属性值的name来确定匹配的路由,通过params来传递参数
3、使用path来匹配路由,通过query(Q瑞)来传递参数
七、vue2和vue3的区别
1、vue3中template(贪铺雷特)支持多个根标签
2、使用setup取代data,methods
3、vue3有createApp(可瑞A特app)(),而vue2的是new vue(
4、vue2中的插槽使用是slot,而vue3是v-slot
八、怎么实现盒子居中
1、使用定位,设置上下左右为0,margin设置aout
2、给父盒子设置定位,top-50%,laft-50%,margin-top和left减去盒子内容的一半
3、给父组件设置弹性盒:使用margin:auto实现居中
九、图片和文字怎么对齐
十、如果实现BFC
1、overflow:hidden
2、浮动
3、绝对定位元素
4、overflow:auto,scroll
十一、你遇到过哪些兼容问题
1、浏览器默认的margin和padding不同:使用通配符*{margin:0,padding:0}
2、png24位的图片在ie6浏览器上出现背景 :做成png8
3、chrome(谷歌)中文界面下默认会将12px的文本强制安装12px显示 :添加css属性webkit-text-size-adjust(ad:额):none
十二、js为什么是单线程的
因为js是操作DOM的,如果js是多线程的,想象一下如果俩个js去操作同一个DOM,那么他就不知道该听谁的了
十三、js既然是单线程的,为什么可以执行异步
因为如果没有异步的话,那上下文如果上一行代码执行很久的话,,就会导致阻塞
十五、改变原数组的方法
1、shift(数组中的第一个元素删除 )
2、unshift (开头添加一个或者多个)
3、push(末尾添加一个或者多个元素)
4、sort (数组排序)
5、pop(删除并返回数组的最后一个元素)
6、reverse(颠倒数组中元素的顺序)
7、splice(从数组中添加删除项目)
十六、react的组件通信
1、props 父组件向子组件通过props传参
2、实例方法--在父组件中可以用refs引用子组件,之后就可以调用子组件的实例方法
3、回调函数--用于子组件向父组件通信,子组件调用props传递过来的方法
4、状态提升--俩个子组件可以通过父组件定义的参数进行传参
5、context上下文一般用做全局主题
6、render props--渲染细节又父组件控制
7、状态管理,通过在view中触发action,改变state,进而改变其他组件的view
十七、jsx语法是什么
jsx语法就是符合xml规范的语法,(语法格式相对来说,要比html严谨)
增强js语义
代码模块化
十九、虚拟dom和真实DOM
虚拟DOM不会进行排版与重绘操作,虚拟DOM就是把真实dom转换成js代码
虚拟dom进行频繁修改,然后一次性比较并修改真实dom值需要该的部分,最后在真实dom中进行排版与重绘,减少过多的dom节点排版与重绘损耗
二十、es6新增了那些新特性
1、增加了箭头函数,箭头函数没有this指向,需要注意this执行的问题
2、新增了解构赋值,可以把数组或者对象当中的值解构出来进行赋值
3、三点展开语法,
4、let和const
5、call和play
6、class类的继承
7、promise
二十一、const和let的区别
const修改他的值不会报错,因为他是引用类型的,他的地址没有发生改变,你只是修改了他的值,如果是const一个对象,你把对象覆盖了,他就会报错,因为你把他的地址改变了
let和const声明都会形成块作用域,同一作用域下let和const不能声明同名变量
使用let和const声明的变量在当前作用域存在暂存死区
const一旦声明就必须赋值。不能使用null占位,声明后不能修改
二十二、call、apply和bind有什么区别
1、call方法调用一个函数,其具有一个指定的this值和分别提供的参数
2、apply方法调用一个函数,具有一个指定的this值,以及作为一个数组提供的参数,apply与call非常相似,不同之处在于提供参数的方式,apply使用参数数组而不是一组参数列表,如果声明的是复合类型数据,可以修改其属性
3、bind函数会创建一个新函数,新函数与被调函数具有相同的函数体,当目标函数被调用时,this值绑定到bind的第一个参数,该参数不能被重写,绑定函数被调用时,bind也接收预设的参数提供给原函数
4、call性能要比apply好一些,传递参数3个以内的话性能差不多,超过3个以上call更好一些
二十三、es5继承和es6继承的区别
es5的继承:直接修改this的指向,把父类的this指向子类,实现最简单的继承
es5的继承:实质上是先创建子类的实例对象,然后再将父类的方法添加到this上
es5的继承通过原型或者构造函数机制来实现
es6的继承:而es6的继承实质上是先创建父类的实例对象this,所以必须先调用父类的super()方法然后在用子类的构造函数修改this
二十三.1、除继承外还有什么区别
es6通过class关键字定义类,里面有构造方法,类之间通过extends关键字实现继承
二十四、箭头函数和普通函数有什么不同
1、相比普通函数写法更加简洁
2、没有this,捕获其所在上下文的this值,作为自己的this值
3、不能使用new,箭头函数作为匿名函数,是不能作为构造函数的,不能使用new
4、使用call()和apply()调用:由于this已经在词法层面完成了绑定,通过call或apply调用一个函数时,只是传入参数而已,对this并没有什么影响者啊
6、箭头函数没有原型属性
7、箭头函数不能当做generator函数,不能使用yield关键字
8、箭头函数不能换行
二十五、promise避免回调地狱的语法糖--实现链式调用的核心点是什么
在then中创建的promisse,他的状态变为fulfilled(佛费哦特)的节点是在上一个promise的回调执行完毕的时候,也就是说当一个promise的状态被fulfilled之后,会执行其回调函数,而回调函数返回的结果会被当做value返回给下一个promise同时下一个promise的状态也会被改变,执行resolve或者reject,然后再去执行其回调,以此类推下去
二十六、箭头函数的this
由于箭头函数不绑定this,他会捕获其所在上下文的this值,作为自己的this值
1、所以call()/apply/bind()方法对于箭头函数来说只是传入参数,对他的this毫无影响
2、考虑到this是词法层面上的,严格模式中与this相关的规则都将被忽略
作为方法的箭头函数this指向全局window对象,而普通函数则指向调用他的对象
二十七、说一下你对原型链的理解
因为每个对象和原型都有原型,对象的原型指向原型对象,而父的原型又指向父的父,这种原型层层链接起来的就构成了原型链
二十八、你对事件循环有了解吗?
所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
主线程之外,还存在一个”任务队列”(task queue)。只要异步任务有了运行结果,就在”任务队列”之中放置一个事件。
一旦”执行栈”中的所有同步任务执行完毕,系统就会读取”任务队列”,看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
主线程不断重复上面的第三步。
主线程从”任务队列”中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。只要主线程空了,就会去读取”任务队列”,这就是JavaScript的运行机制。这个过程会循环反复。
二十九、异步解决方法有哪些?
1、回调函数cllback,缺点:多个回调函数嵌套,是代码看起来很混乱,不易于维护
2、事件发布订阅 缺点:消耗内存,过度使用会使代码难以维护和理解
3、promise
4、generator
5、aync /await
三十、什么是防抖
防抖就是高频事件后n秒内函数只会执行一个,如果n秒内高频事件再次被触发,则重新计算时间
三十一、什么是节流
在单位时间内,只会触发一次事件,如果事件触发后,又重复触发了同一事件,则忽略后面触发的事件,直到第一次事件的计时结束
三十二、hash和history 的区别
hash模式下,仅hash符号之前的内容会被包含在请求中,如果http://www.abc.com因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回404错误;
history模式下。前端的url必须和实际后端发送请求的url一致,如http://www.abc.com/book/id,如果后端缺少对/book/id的路由处理,将返回404错误
三十三、使元素消失的方法
1、display: none ,使元素从页面彻底消失,会造成页面的回流与重绘
2、visbility:hidden,元素会从页面中消失,但是原本占据的空间会被保留,适用于希望元素隐藏又不影响布局
3、opacity,给元素设置成透明
4、设置盒模型属性为0
5、使用元素绝对定位,将元素移除屏幕
6、z-index覆盖
三十四、防抖和节流的应用场景
比如登录发短信等按钮避免用户点击太快,以致于发送了多次请求,
调整浏览器窗口大小时,resize次数过于频繁,造成计算过多,此时需要一次到位,就需要防抖
节流:scroll窗口滚动事件,每个一秒计算一次位置信息等,
浏览器播放事件,每隔一秒计算一次进度信息等
iput框实时搜索并发送请求展示下拉列表,每隔一秒发送一次请求
react生命周期函数
三十六、js原型
js每个函数都有一个protorype对象属性,指向另一个对象,原型链上,
prototype的所有属性和方法,都会被构造函数继承的实例继承,这意味着,我们可以把那些不变的属性和方法,直接定义在prototype上
prototype就是调用构造函数所创建的那个实例对象的原型
三十七、双向绑定的原理
vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()
来劫持各个属性的setter
,getter
,在数据变动时发布消息给订阅者,触发相应的监听回调。在设置或者获取的时候我们就可以在get或者set方法里假如其他的触发函数,达到监听数据变动的目的
响应式原理
vue的响应式实现主要是利用了Object.defineProperty的方法里面的setter 与getter方法的观察者模式来实现。在组件初始化时会给每一个data属性注册getter和setter,然后再new 一个自己的Watcher对象,此时watcher会立即调用组件的render函数去生成虚拟DOM。在调用render的时候,就会需要用到data的属性值,此时会触发getter函数,将当前的Watcher函数注册进sub里。当data属性发生改变之后,就会遍历sub里所有的watcher对象,通知它们去重新渲染组件。
订阅者模式
它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。
优点:支持简单的广播通信,当对象状态发生改变时,会自动通知已经订阅过的对象。
缺点:
.创建订阅者需要消耗一定的时间和内存。
2.虽然可以弱化对象之间的联系,如果过度使用的话,反而使代码不好理解及代码不好维护等等。
三十八、vue组件通信方式
1、props :父组件向子组件传递数据是通过prop传递的
2、emit触发事件来做到的
3、ref:父组件通过设置子组件ref来获取数据
4、EVentbus:中央事件总线:兄弟组件传值,一个是用this.emit,另一个是用this.on
5、通过共同祖辈root搭建通信侨联
6、vuex
三十九、作用域链
当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级执行上下文的变量对象中查找,一直找到全局上下文的变量,这样由多个执行上下文的变量对象构成的链就叫做作用域链
四十、解释下let和const的块级作用域
let声明的仅在块级作用域内有效
let不会发生变量提升的现象,所有一定要在定义后使用,否则报错
不允许重复声明,let不允许在形同作用域内,重复声明同一个变量
const声明一个只读变量,一旦声明,常量的值就不能改变
一旦声明就有理解初始化,否则也会报错
const命名的变量也不提升,同样存在暂时性死区,只能在声明的位置后使用,也不可以重复声明
四十一、原型链
原型链:在访问对象的属性和方法是,会在当前对象中查找,如果没有找到,会一直沿着原型链上的原型链上的原型对象proto向上查找,直到找到object.prototype为止
四十二、闭包
闭包的作用:
1、在外部访问函数内部的变量
2、让函数内的局部变量可以一直保存下去
3、模块化私有属性和公共属性
闭包的原理:
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
闭包的应用场景:
1、返回值
2、函数赋值
3、函数传参
4、循环赋值
5、getter和setter
6、迭代器
7、触发事件
闭包的this指向问题
1、this指向window对象,因为匿名函数的执行具有全局性,所以在其this对象指向window
闭包的缺点:
占用内存空间,大量使用闭包会造成栈溢出
闭包优化:
由于闭包会一直占用内存空间,直到页面销毁,我们可以主动将已使用的闭包销毁,将闭包函数赋值为null,可以销毁闭包
四十三、介绍一下类型转换
显式转换
1、tostring()转换成字符串,不可以转换null和underfind
2、Nunber()转换为数字,字符串中有一个不是数值的字符,返回NAN
3、parseInt()转换为数字,第一个字符表示数值的字符,返回NaN
4、string()转换成字符串
5、boolean()转换成布尔值
隐式转换
1、当加号运算符时,string和其他类型时,其他类型都会转为string,其他情况,都转化为Number类型
2、其他运算符时,基本类型都转换为Number
对象和布尔值进行比较时,对象先转换为字符串,然后再转换为数字,布尔值直接转换为数字
四十四、类组件和函数组件的区别
1、语法上函数组件是一个函数,返回一个jsx元素,而类组件是es6语法糖class定义,继承component类
2、类组件中可以通过state进行状态管理,而在函数组件中不能使用setstate(),在react16.8以后函数组件可以通过hooks中的usestate来模拟类组件中的状态管理
3、类组件中有一系列的生命周期钩子函数,在函数组件中也需要接组hooks来使用生命周期函数
4、类组件 能够捕获最新的值,这是因为当实例的props属性发生修改时,class组件能够直接通过this捕获到组件最新的props,而函数式组件是捕获渲染所使用的值,因为js闭包的特性,之前的props参数保存在内存之中,无法从外部进行修改
四十五、请你说说react的路由是什么
路由分为前端路由和后端路由,后端路由时服务器根据用户发起的请求而返回不同的内容,前端路由是客户端根据url去切换组件,在web应用前端开发中,路由系统是最核心的部分,当页面的url发生改变时,页面的显示结果可以根据url的变化而变化,但是页面不会刷新
react生态中,路由通常是使用react-router来进行配置,其主要构成为:
1、router---对应路由的俩种模式,包括<browsers(不绕生死)router >与<hashrouter>
2、router matching(吗群)组件---控制路径对应的显示组件,可以进行同步加载和异步加载<router>
3、navigation(啦为给瞬)组件---用作路由切换和跳转《link》
browserrouter与hashrouter的区别
1、底层原理不一样,browserrouter使用的是h5的history,hashrouter使用的是url的哈希值
2、path表现形式不一样,browserrouter的路径中没有#,hashtory的路径包含#号
3、刷新后对路由state参数的影响,browserrouter没有任何影响,因为state保存在history对象中,hashrouter刷新后会导致路由state参数的丢失
四十六、react有哪些性能优化的手段
1、使用纯组件
2、使用reactmemo进行组件记忆,对于相同的输入,不重复执行
3、如果是类组件,使用shouldcompoentupdate生命周期事件,可以利用此事件来决定何时需要重新渲染组件
4、路由懒加载
5、 不要使用内联函数定义,(如果我们使用内联函数定义,则每次调用render函数时,都会创建一个新的函数实例
6、避免在will系列的生命周期中进行异步请求,操作dom等
7、如果是类组件,事件函数在constructor中绑定bind改变this指向
8、避免使用内联样式属性
9、不要在render方法中导出数据
10、列表循环的时候加上key
11、在函数组件中使用usecallback和usememo来进行组件优化,依赖没有变化的话,不重复执行
12、类组件中使用immutable(衣谬特拨)对象
四十七、react hooks用过吗,为什么要用?
用过 ,hooks是react在16.8版本中出的一个新功能,本质是一种函数,可以实现组件逻辑复用,让我们在函数式组件中使用类组件中的状态,生命周期等功能,hooks的名字都是use开头
使用过那些hooks属性
1.usestate--创建状态
接收一个参数作为初始值,返回一个数组,第一个值为状态,第二个值为改变状态的函数
2、useEffect(数据获取,dom操作影响页面)
当第二个参数为空时,相当于模拟了挂载生命周期函数(componentdidupdate),只会执行一次,第二个参数如果是传入的依赖列表时,就模拟了componentdidupdate,依赖列表更新后触发,如果第二个参数是return的话,就是返回要销毁的一些数据内容。
3、useref
返回一个可变的ref对象,此索引在整个生命周期中保持不变,,可以用来获取元素或组件的实例
4、usememo ----优化函数组件中的功能函数----在渲染期间执行
接收一个函数作为参数,同样接收第二个参数作为依赖列表,返回值可以是任何函数对象等都可以
这种优化有助于避免在每次渲染时都进行高开销的计算,仅会在某个依赖改变时才会重新计算
5、usecontext---获取上下文注入的值
6、uselayouteffect(雷奥特) ----有dom 操作的副作用---在dom更新后执行
和useeffect类似,但是执行时机不同,uselayouteffect在dom更新之后执行。useeffect在render渲染结束后执行,也就是说uselayouteffect比useeffect先执行,这是因为dom更新后,渲染才结束,或者渲染才会结束
7、usecallback ---与usememo类似
通过usecallback包裹的方法来达到缓存效果,即usecallback包裹项的属性或者值不变时,不重新生成
8、usehistory---跳转路由
9、uselocation---得到url对象
10、useparams---得到url上的参数
四十八、react的渲染过程
jsx通过beble编译,转换成react.createElement,在render方法执行后,返回一个element对象,
这时候我们会判断element的类型,如果是null、false则实例一个ReactDOMEmptyComponent对象; 是string、number类型的话则实例一个ReactDOMTextComponent对象; 如果element是对象的话,会进一步判断type元素类型,是原生dom元素,则实例化ReactDOMComponent; 如果是自定义组件,则实例化ReactCompositeComponentWrapper;
在这些类生成实例对象的时候,在其内部会调用 mountComponent方法,这个方法里面有一系列浏览器原生dom方法,可以将element渲染成真实的dom并插入到文档中;
四十八、虚拟DOM的优劣如果,实现原理
虚拟dom是用js模拟一颗dom树,放在浏览器内存中,相当于在js和真实dom中添加了一个缓存,利用dom diff算法避免了没有必要的dom操作,从而提高性能
优点:
1、虚拟dom具有批处理和高效的diff算法,最终表现在dom上的修改只是变更的部分,可以保证非常高效的渲染,优化性能
2、虚拟dom不会立马进行排版与重绘操作,对虚拟dom进行频繁修改,最后一次性比较并修改真实DOM中需要修改的部分
3、虚拟dom有效降低大面积真实dom的重绘与排版,因为最终于真实dom比较差异,可以值渲染局部
缺点:
首次渲染大量dom时,由于多了一层虚拟dom的计算,会比innerheml插入慢
四十九、async和await、promise的区别,和这俩个的本质
promise是一笔编程的一种解决方案,比传统的解决方案,回调函数和事件更强大,简单的说,promise好比容器,里面存放这一些未来才会执行完毕的事件的结果,而这些结果一旦生成是无法改变的
async await也是异步编程的一种解决方法,他遵循的是generator函数的语法糖,他拥有内置执行器,不需要额外的调用直接会自动执行并输出结果,它返回的是一个promise对象
俩者的区别:
promise的出现解决了传统callback函数导致的回调地狱问题,但他的语法导致了他纵向发展成了一个回调链,遇到复杂的业务场景,这样的语法陷入也是不美观的,而async await代码看起来会简洁些,使得异步代码看起来像同步代码,await的本质是可以提供等同于同步效果的等待异步返回能力的语法糖,只有这一句代码执行玩,才会执行下一句
async和await与promise一样,是非阻塞的
async await是基于promise实现的,可以说是改良版的promise,他不能用于普通的回调函数
五十、简述ayncawait的好处
1、async/await最重要的好处是同步编程风格
2、async/aawait有本地浏览器支持,截止今天,所有主流浏览器,查看都完全支持异步功能
3、async关键字,他声明函数返回值确保是一个promise,以便调用者可。。、以安全调用
五十二、flux核心思想是什么
Flux的核心思想就行数据和逻辑永远单向流动,由三大部分组成,dispatch,store和view,redux和vuex是flux思想的具体实现,都是用来做状态管理的工具
五十三、react生命周期
开始阶段:
1、constructor(在构造函数挂载之前被调用)
2、render
3、componentdidmount(在组件被装配后立即调用)
更新阶段:
shouldcomponentUpdata(更新前)
render
componentDidupdate(更新后立即调用)
卸载阶段、销毁阶段
componentwillunmout
constructor生命周期:
当react组件实例化时,是第一个运行的生命周期
在这个生命周期中,不能使用this.setstate()
不能把props和state交叉赋值
componentDidMount生命周期:
相当于是vue中的mounted
他表示DOM结构在浏览器中渲染已完成
shouldcomponentupdate生命周期:
相当于一个开关,如果返回true则更新机制正常执行,如果为false则更新机制停止
在vue中是没有的
存在的意义,可以用于性能优化,但是不常用,最新的解决方法是使用purecomponent
componentdidcatch:
在渲染过程中抛出错误时
componentDidUpdate生命周期:
相当于vue中的updated()
他表示dom结构渲染更新已完成,只发生在更新阶段
在这里,可以执行大多数的副作用,但是不建议
在这里,可以使用this.setstate(),但是要有终止条件判断
componentWillUnmount生命周期:
一般在这里清除定时器、长链接等其他占用内存的构造器
render生命周期:
render是类组件中唯一必须有的生命周期,同时必须有return
可以使用空标签
return之前,可以做任意的业务逻辑,但是不能使用this.setstate(),会造成死循环
render在装载阶段和更新阶段都会运行
当render方法返回null的时候,不会影响生命周期函数的正常执行
五十四、什么是受控组件
表单的value值受state数据的控制,配合changge事件修改state的值,value的值就会自动跟着改变
五十五、什么是非受组件
简单来说,就得DOM的那种处理方式
五十六、diff和key之间的联系
列表渲染,react会在创建时要求为每一项输入一个独一无二的key,这样就能高效的diff运算,比如我们要在b和c节点之间插入一个节点f,jq会将f这个节点后面的每一个节点都进行更新,比如c更新成f,d更新成c,这样操作的话就会特别的多,而加了key的react不会频繁的操作dom,而是优先采用移动的方式,找到正确的位置去插入新节点,所以我们不能省略key值,因为在对比俩个新旧的子元素是通过key值来精确的判断俩个节点是否为同一个,如果没有key的话则是见到谁就更新谁,非常消耗性能
五十七、单向数据流和双向数据绑定的理解,好处
像只允许父组件像子组件传值的这种方法就是单向数据流,但是利于维护
双向数据流代码编写方便,但是不利于维护
五十八、props和state的区别
props是外部传入组件的参数,一般用于父子组件之间的通信,state一般用于组件内部的状态维护,更新组件内部的数据,props不可以在组件内部修改,只能通过父组件进行修改,state在组件内部通过setstate修改
五十九、redux本来是同步的,为什么他可以执行异步代码,中间件实现的原理是什么
六十、列举重新渲染render的情况
接受到新的props
通过状态管理等
改变上下文
六十一、react按需加载
1.使用react.lazy,懒加载
2、使用loadable components这个库,实现方法跟懒加载差不多
六十二、如果我进行三次setstate会发生什么
看情况:如果是在原生js空间,则会同步执行,修改state的值,调用三次render函数,如果是在react函数空间下,则会进行合并,只修改一次state的值,调用一次render
六十三、渲染一个react组件的过程
先经过babel编译,通过jsx语法转化成react.createelement,在通过element生成真实节点,在生成真实节点后,进行生命周期的执行
六十四、类组件和函数式组件怎么做性能优化
1、使用shouldcomponentUpdate这个生命周期决定当前状态或者属性的改变是否重新渲染组件
2、组件复用
函数式组件:
usecallback
usememo记忆组件,相同的输入不改变
六十五、useeffect和uselayouteffect的区别
主要的区别就是他们的执行时机不同,在浏览器中js线程与渲染线程是互斥的,当js线程执行时,渲染线程呈挂起状态,只有当js线程空闲是渲染线程才会执行,uselayout在js线程执行完毕即dom更新之后执行,而useeffect是在渲染结束后才执行,也就是说uselayouteffect 比useeffect先执行
六十六、hooks的使用有什么注意事项
只能在react函数式组件或自定义hook中使用hook
不要在循环条件或嵌套函数中调用hooks,必须始终在react函数的顶层使用hooks
六十七、纯函数有什么特点,副作用函数特点
纯函数与外界交换数据只有一个唯一的返回值,纯函数是无状态的,线程安全,纯函数相互调用组装起来的函数,还是纯函数,应用程序或者运行环境可以对纯函数的运算结果进行缓存,运算加快速度
副作用的特点是:除了返回函数值之外,还对主调用函数产生附加影响,比如掉接口,修改全局变量、抛出一个异常等
六十八:react中的refs干嘛用的
refs是react提供给我们的安全访问dom元素或某个组件实例的句柄
六十九、为什么不直接更新state
如果试图直接更新state,则不会重新渲染,需要使用serstate方法更新state
七十、调用this.setstate之后,react都做了哪些操作?怎么拿到改变后的值
如果是隶属于原生js执行的空间,比如说settimeout里面,setstate是同步的,那么每次执行setstate将立即更新this。state,然后触发render方法
如果是在被react处理过的空间执行,比如合成事件里,此时setstate是异步执行的,并不会立即更新this.state的值,当执行setstate的时候,会将需要更新的state放入状态队列,在这个空间最会在合并修改this.state,触发render
七十一、generator和promise,async/await
generator也是一种处理异步的解决方法,他在需要处理异步的代码前加上*号,在后面加上yeid,但是generator方法需要在每行代码都加上yeid,这样就会比较麻烦,promise也是一种解决异步的方法,promise相对于传统解决方法更合理更强大,简单的说,promise好比容器,里面存放着一些未来才会执行完毕的事件的结果,但是处理异步比较多的话,也就是一直.then,也会使代码美观,不好处理与维护,async/await是es6新增的异步解决方案,他遵循的是generator函数的语法糖,他拥有内置执行器,不需要额外的调用直接会自动执行并输出结果,他返回的是一个promise对象,可以理解async就是优化版的promise,async使代码看起来更加简洁,从上至下执行
七十二、什么是订阅者模式
他定义了对象见的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象 都将得到通知
七十三、什么是react -context
context提供了一个无需为每层组件手动添加props,就能在组件树之间进行数据传递的功能
某些全局属性,通过父子props传递太过繁琐,context提供了一种组件之间共享此类值的方式,而不必显示的通过组件数逐层传递props
七十四、如果在react的props上应用验证
使用proptype进行类型检查
我们在组件类下添加一个静态属性proptypes,他的值也是一个对象,用来设置组件中props的验证规则,key是要验证的属性名称,value是验证规则
七十五、在react中使用构造函数和getinitial(因内修)state有什么区别
区别在于es6和es5本省,getinitialstate是搭配react.createclass使用的,constructor是搭配react.component使用的
在react的生命周期中,constructor先与getlnitialstate
七十六、如何有条件地向react组件添加属性?
对于某些属性,react足够只能可以忽略该属性,比如值为boolean值属性的值,也可以写控制语句管理是否给组件添加属性
七十七、hooks会取代render props和高阶组件吗
可以取代,但没必要
在hook的渐进策略中也有提到,没有计划从react中移除class,在新的代码中同时使用hook和class,所以这些方案目前还是可以有用武之地
七十八、如何避免组件的重新渲染
当props/sate改变时组件会执行 render函数重新渲染
class组件中们可以使用shouldcomponentUpdate钩子函数
Purecomponent默认有避免重新渲染的功能(prrecomponent如果组件的props和state都没发生改变,render方法就不会更新
函数组件使用高阶组件memo处理
七十九、虽然HOC&RenderProps能处理逻辑复用的问题,但是却存在各自的问题
HOC存在的问题:
写法破坏了原来组件的结构,devtools(吐死)中组件会形成嵌套地狱
不要在redner方法中使用HOC,每次调用render 函数会创建一个 新的高阶组件导致该组件及其子组件的状态丢失
需要修复静态方法,即拷贝源组件的静态方法到高级组件中
八十、http协议
客户端和服务器签订的一种标准,你去请求和响应都是按照这个标准请求
八十一、3次捂手4次挥手
当客户端向服务端请求数据报文,然后服务端收到前端请求报文后向客户端发送确认报文,客户端收到确认报文后,向服务端回复确认可以接收数据,然后服务端就可以开始向客户端发送数据,
1/TCP链接
2、web浏览器向web服务器发送请求命令
3、web浏览器发送请求头信息
4、web服务器应答
5、web服务器发送应答头信息
6、web服务器向浏览器发送数据
7、文本服务器关闭tcp链接
八十二、antd里面的message是怎么实现的
给他一个定位,通过监听点击事件,当点击的时候触发效果,添加一个出场动画,设置一个定时器,多少秒后消失
八十三、usestate为什么重新渲染时不会重置数据
八十四、怎么实现一个0.5像素的线
高度设置为0.5px
或者定义一个1px的线,使用缩放(0.5)
八十五、状态码
服务端返回的状态码,
100 | Continue | 继续。客户端应继续其请求 |
---|---|---|
101 | Switching Protocols | 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议 |
200 | OK | 请求成功。一般用于GET与POST请求 |
201 | Created | 已创建。成功请求并创建了新的资源 |
202 | Accepted | 已接受。已经接受请求,但未处理完成 |
203 | Non-Authoritative Information | 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本 |
204 | No Content | 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档 |
205 | Reset Content | 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域 |
206 | Partial Content | 部分内容。服务器成功处理了部分GET请求 |
300 | Multiple Choices | 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择 |
301 | Moved Permanently | 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 |
302 | Found | 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI |
303 | See Other | 查看其它地址。与301类似。使用GET和POST请求查看 |
304 | Not Modified | 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源 |
305 | Use Proxy | 使用代理。所请求的资源必须通过代理访问 |
306 | Unused | 已经被废弃的HTTP状态码 |
307 | Temporary Redirect | 临时重定向。与302类似。使用GET请求重定向 |
400 | Bad Request | 客户端请求的语法错误,服务器无法理解 |
401 | Unauthorized | 请求要求用户的身份认证 |
402 | Payment Required | 保留,将来使用 |
403 | Forbidden | 服务器理解请求客户端的请求,但是拒绝执行此请求 |
404 | Not Found | 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面 |
405 | Method Not Allowed | 客户端请求中的方法被禁止 |
406 | Not Acceptable | 服务器无法根据客户端请求的内容特性完成请求 |
407 | Proxy Authentication Required | 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权 |
408 | Request Time-out | 服务器等待客户端发送的请求时间过长,超时 |
409 | Conflict | 服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突 |
410 | Gone | 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置 |
411 | Length Required | 服务器无法处理客户端发送的不带Content-Length的请求信息 |
412 | Precondition Failed | 客户端请求信息的先决条件错误 |
413 | Request Entity Too Large | 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息 |
414 | Request-URI Too Large | 请求的URI过长(URI通常为网址),服务器无法处理 |
415 | Unsupported Media Type | 服务器无法处理请求附带的媒体格式 |
416 | Requested range not satisfiable | 客户端请求的范围无效 |
417 | Expectation Failed | 服务器无法满足Expect的请求头信息 |
500 | Internal Server Error | 服务器内部错误,无法完成请求 |
501 | Not Implemented | 服务器不支持请求的功能,无法完成请求 |
502 | Bad Gateway | 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应 |
503 | Service Unavailable | 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中 |
504 | jGateway Time-out | 充当网关或代理的服务器,未及时从远端服务器获取请求 |
505 | HTTP Version not supported | 服务器不支持请求的HTTP协议的版本,无法完成处理 |
八十六、说一下你对promise的理解
promise是一个异步解决的方案,他比传统的解决方案更合理更强大,es6将其写进了语言标准,统一了用法,promise对象是一个构造函数,用来生成promise实例
promie就是为了解决回调地狱而产生的,promise有俩个特点,promise对象的状态不受外界影响
promise有三种状态,进行中,成功和失败,只有异步操作的结果可以决定当前是哪一种状态
promise支持链式的写法
八十七,说一说你对性能优化的了解
八十八、http和https区别
https是在http上多了一层加密协议,在https发送请求时,给你的数据加密,返回数据的时候也会给你加密,而http就是你发送数据的生活是明文发送,返回的时候是明文返回
八十九、js继承是什么
如果是通过类组件实现继承,通过extends实现继承
一个对象想要获取另一个对象的属性和方法,就可以通过原型的方式继承,在proptype上定义方法和属性
九十、跨域的概念是什么
由于浏览器的同源策略,为了防范跨站脚本的攻击,禁止客户端脚本对不同域下的文档或脚本进行跨站调用资源,
跨域就是他的端口,协议,域名有一个不相同,就会出现跨域
解决方案:img、script这种的标签就可以解决跨域问题,
jsonp。和node代理
九十一、rem是怎么计算的
rem是通过根元素进行适配的,1rem就等于html中的fontsize的16px,1rem就等于*16px像素
可以通过26.6667vm,实现布局计算,然后我们在设置字体的时候除以100,然后加上rem即可
九十二、js存储有哪些
sessionstorage :用于临时保持同一窗口的数据,窗口关闭数据也将删除
localstorage:本地存储,同时不受时间限制的数据存储,localsorage一般浏览器支持的是5,m大小
cookie:用于存储web页面的用户信息,当用户访问web页面是时,他的名字可以记录在cookie中,在用户下一次访问该页面是,可以在cookier中读取用户访问记录,客户端cookie数量最多为300个,每个不能超过4kb,每个web站点设置的cookie数量不能超过20个
九十三。箭头函数除了书写简单以外还有什么作用
利用箭头函数没有this指向特性,在需要使用外部this的情况下,就可以使用箭头函数获取上下文的this,
九十四、你对安全有什么了解
,使用https协议加密请求
xss攻击,必须限制用户进行脚本或者其他输入,避免黑客对脚本进行解析攻击
MD5
九十五、js有哪些继承方法
1、class类继承,通过extnds实现继承
2、通过改变this指向实现继承
3.prototype继承,在prototype原型链上设置属性实现继承
九十六、什么是响应式布局
响应式布局就是网页能够根据屏幕宽度自适应,达到屏幕的适配
九十七、什么是事件循环
事件循环就是,在执行同步代码过程中,假设你要打印一个console.log,在执行的过程中,碰到了想定时器延时器这类的方法,他就会将定时器放到宏任务中,然后再往下执行,然后执行的过程中,遇到了promise这类的异步请求,他就会将.then这些放到微任务中,然后再执行打印,执行玩打印之后,在回到为任务中,将微任务中的队列清除,再去看宏任务中有没有任务,如果在宏任务中遇到了新的异步方法,会将异步放入微任务,然后将微任务的队列清除
九十八、事件绑定原理是什么
React的事件绑定,是通过在react元素上添加事件属性,且事件属性名必须采用驼峰命名的方式,如onClick等。
九十九、高阶组件的好处是什么
高阶组件是一个函数,它接受一个组件并返回一个新组件。高阶组件(HOC)是React中重用组件逻辑的一种高级技术。hoc本身不是React API的一部分,是由 React的组合特性而来的一种设计模式
一百、aixos是基于什么封装的
aixos是一个基于promise的http库,支持promise所有的api
他可以拦截请求,和响应
他可以转换请求数据和响应数据,并对响应来的内容转换成json类型的数据
安全性更高,客户端支持防御xsrf
一百零一、axios有哪些常用的方法
get。请求列表和信息查询
delete删除
post请求用于信息的添加
put更新操作
一百零一、aixos的相关配置属性
url是 用于请求的服务器URL,
method是创建请求时使用的方法是get
baseurl将自动加在url的前面,除非url是一个绝对的url,他可以通过设置一个baseurl 便于为aixos实例的方法传递相对url
trabsfromrequest 允许在向服务器发送前,修改请求数据,只能在put,post和patch这几个请求方法,
herms是即将与请求一起发送的url参数,必须是一个无格式对象,或urlsearchparams对象
auth表示应该使用http基础验证,并提供凭据,这将设置一个authorization头,覆写掉现有的任意使用,headers设置的自定义authorization头
auth表示http基础验证应当用于链接代理,并提供凭据
一百零二、getter和setter
一、getter
按照客户的期望返回格式化数据
控制服务的顺序(列如只有当连接建立时getter方法才返回相应实例)
二、setter
可以限制和检验setter方法传入的参数
隐藏对象内部数据结构
一百零二、web前端,如果提高性能优化
数据懒加载:不显示的东西不加载,需要显示了才加载
小图标用精灵图,合并成一张字库,用gb2312
,不要utf-8,一个汉字少一个字节
图片用base64
路由懒加载、组件不用不加载
使用webpack等工作压缩html、js、css代码
一百零三、什么叫优雅降级和渐进增强
优雅降级:能力检测,如果能力有用新的,如果能力没有,用旧的
渐进增强:低端浏览器仅实现基本功能,高级浏览器实现额外功能,
比如上传文件,低端浏览器就给他提供上传按钮,高端浏览器提供拖拽文件上传
一百零四、bfc的形成
有明确的宽度高度盒子
overflow:hidden
定位,浮动
display:inline-block
特质:内部有浮动,能清除这些浮动,能为浮动元素撑高
一百零五、实现6px大小的子
transfrom:scale(。5)
一百零六、移动端1px边框的问题
使用宽高加背景色
使用box-shadow(盒子阴影)
使用border-image
一百零七、对单位px、em、rem、vh、vw的理解
px物理像素,绝对值
em相对于父级的大小,相对值
rem相对于html的大小,
vh相对于屏幕的高度
vw相对于屏幕的宽度
一百零八、如果减少重绘和回流
通过className或者classtext一次性修改样式,而非一个一个改
离线模式:克隆要操作的节点,操作后再与原始节点交换,类似于虚拟dom
避免频繁直接访问计算后的样式,而是先将信息保存下来
绝对布局的dom,不会造成大量reflow
div不要嵌套太深,不要超过6层
一百零九、谈谈你对html5的理解
html5是一个规范,标签更具有语义化,如(header、footer之类的)
css3新增了很对新特性,使得页面更美观,(shadow(盒子阴影)gradient(渐变))等,动画过度等新特性更节约页面性能,还提供了大量api,列如本地储存,离线缓存application cache,地理定位geolocation、及时会话websocket、文件预览filereader等
一百一十、深浅克隆
浅克隆就是表层克隆,就是用for in 或者for循环赋值对象、数组的一层,如果他的某个属性值又是引用类型值,则仍然是内存中的同一个对象
深克隆,需要使用递归
一百一十一、ajax原理
创建XMLHTTPRqusest对象
open设置请求方式
调用回调函数
发送请求,send
一百一十二、跨域
跨域是值一个域下的文档或脚本试图请求另一个域下的资源,是由浏览器同源策略限制的一类场景,协议+域名+端口三者只要有一个不相同就是同源
1、使用cors跨域
2、node代理
3、jsonp。src
一百一十三、get请求和post请求的区别
get在浏览器回退时是无害的,而post会再次提交请求
get产生的url地址跨域被bookmark(标签,标记),而post不可以
get请求会被浏览器主动cache(缓存),而post不会,除非手动设置
get请求只能进行url编码,而post支持多种编码方式
get请求参数会被完整保留在浏览器历史记录里,而post中的参数不会被保留
get请求在url中传送的参数是有长度限制的,而post没有
对参数的数据类型,get只接收ascll字符,而post没有限制
get比post更不安全,因为参数直接暴露在url上,所有不能用来传递敏感信息
get参数通过url传递,post放在requsest body中
一百一十四、事件冒泡、事件捕获、和时间委托
事件冒泡会从当前触发的事件目标一级一级往上传递,依次触发,直到document为止。事件捕获会从document开始触发,一级一级往下传递,依次触发,直到真正事件目标为止。事件委托,通过监听一个父元素,来给不同的子元素绑定事件,减少监听次数,从而提升速度。
一百一十五、内存污染、内存泄漏、内存溢出的理解
垃圾回收:一个变量如果不用了,会被程序自动回收。
内存泄露:垃圾回收不了这个东西了,就是内存泄露。内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。
内存溢出:系统会给每个对象分配内存也就是Heap size值,当对象所需要的内存大于了系统分配的内存,就会造成内存溢出
内存污染:变量命名产生冲突
一百一十六、垃圾回收机制
一般来说没有被引用的对象就是垃圾,就是要被清除, 有个例外如果几个对象引用形成一个环,互相引用,但根访问不到它们,这几个对象也是垃圾,也要被清除。
垃圾回收的方法主要有两种:一种是标记清除,即用完之后的变量 赋值成null,另一种是引用计数,将使用完的对象的引用计数,如果为0则回收
一百一十七、构造函数中的new操作符都做了什么
构造函数中没有显示,创建object,实际上后台自动创建了一个空对象,
直接给this对象赋值属性和方法,this即指向创建的对象
没有return返回值,返回自动返回了该对象
该对象继承构造函数的原型
一百一十八、event对象,俩个常用方法、2个属性
event.stopPropagation() 阻止事件继续传播(问你应用场景,你就说悬浮层)
event.preventDefault() 阻止默认事件(问你应用场景,a标签阻止默认刷新页面,拖
拽到页面的时候阻止浏览器默认的打开这个文件的默认事件)
这两个方法不兼容,一些浏览器中:
event.cancelBubbel = true; 阻止事件继续传播
event.returnValue = false; 阻止默认事件
event.target //触发事件的最内层元素
event.keyCode //键盘,13回车,37左按钮
event.target属性不兼容,一些浏览器中:
event.srcElement //触发事件的最内层元素
一百一十九、对promise的理解
promise是es6新增的处理异步的东西、promise的实例有三种状态:pending,resolved,rejected。
promise对象有then方法,用来做resolved的事情,有catch方法,用来做rejected事情。
promise.all可以等所有请求都成功了在执行
promise.race可以竞速执行请求
promise解决了回调地狱的问题
一百二十、async和await的理解
generator函数的语法糖,将*改成async,将yield换成await
是对generrator函数的改进,返回promise
异步写法同步化,遇到awaiw先返回,执行玩异步再执行接下来的
内置执行器,无需next()
一百二十一、for in和 for or 区别
for in 遍历数组会遍历到数组原型上的属性和方法,更适合遍历对象
使用for or可以成功遍历数组的值,而不是索引,不会遍历原型
一百二十二、usememo和usecallback有什么区别
memo是缓存组件的,callback是缓存函数的
一百二十四、requset、和import
requeset是导入文件路径的,是同步的
import是导入模块的,异步的
一百二十五、http的默认端口和https的默认端口
http默认端口是80,https是443
一百二十六、xss攻击怎么解决
xss是跨站脚本攻击,他指的是在地址中恶意输入html脚本代码,
解决方法:过滤输入和转义输出
在输入方面对所有用户提交内容进行可靠的输入验证,提交内容包括url、查询关键字,http头,post数据等
在输出方面 :标签内的内容不会解析,直接显示
一百二十七、cookie和seestoreage
cookie默认存储时间是关闭浏览器就销毁,cookie可以发送到服务器,cookie只有4kb,cookie可以设置过期事件,seestoreage也是关闭就销毁,不能设置时间
一百二十八、mvvm的理解
mvvm是model-view-viewmodel 的缩写。model代表数据模型,view代表ui组件,viewmodel监听模型数据的改变和控制视图行为,简单理解就剩一个同步view和model的对象,在mvvm架构下,view和model之间没有直接的联系,而是通过viewmodel进行交互,model和viewmodel之间的交互是双向的,因此,view数据的变化会同步到model中,而model数据的变化也会立即反应到view上,从而触发视图更新
一百二十九、watch和computed的区别
watch只能监听data中的数据变化,computed不需要,watch可以进行异步操作,computed不可以,computed不修改原始数据,通过return返回处理的数据,可以包含大量的逻辑运算
一百三十、vue单页面应用及其优缺点
优点:vue的目标是通过尽可能简单的api实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统,mvvm数据驱动,组件化、轻量、简洁。高效、快速、只关心数据,不关心dom,插件众多,维护状态方便
缺点:不支持低版本的浏览器,最低只支持ie9,不利于seo(搜索)的优化,第一次加载首页耗时相对长一些,不可以使用浏览器的导航按钮,需要自行实现前进,后退
一百三十一、ssr的理解
更好的seo,搜索引擎爬虫抓取工具可以直接查看完全渲染的页面
更快的内容到达事件,特别是对于缓慢的网络情况或运行缓慢的设备,通常可以产生更好的用户体验,
server运行环境,更多的服务器端负载
一百三十二、hash和history 的区别
1)hash路由在地址栏URL上有#,而history路由没有会好看一点
2)我们进行回车刷新操作,hash路由会加载到地址栏对应的页面,而history路由一般就404报错了(刷新是网络请求,没有后端准备时会报错)。
3)hash路由支持低版本的浏览器,而history路由是HTML5新增的API。
4)hash的特点在于它虽然出现在了URL中,但是不包括在http请求中,所以对于后端是没有一点影响的,所以改变hash不会重新加载页面,所以这也是单页面应用的必备。
5)history运用了浏览器的历史记录栈,之前有back,forward,go方法,之后在HTML5中新增了pushState()和replaceState()方法(需要特定浏览器的支持),它们提供了对历史记录进行修改的功能,不过在进行修改时,虽然改变了当前的URL,但是浏览器不会 马上向后端发送请求。
一百三十三、为什么虚拟dom会提高性能
虚拟dom相当于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的dom操作,从而提高性能,他会将新的树和旧的树进行比较,记录俩棵树的差异从而渲染到真实dom上。
一百三十四、react中的refs的作用是什么?
refs是react提供给我们的安全访问dom元素或者某个组件实例的句柄。我们可以为元素添加ref属性然后再回调函数中接收该元素在dom树中的句柄,该值会作为回调函数的第一个参数返回
一百三十五、展示组件和容器组件之间有何不同
展示组件关心组件看起来是什么,容器组件则更关心组件是任何运作的,容器组件会为展示组件或者其他容器组件提供数据和行为,他们会调用actions,并将其作为回调提供给展示组件
一百三十六、类组件和函数式组件之间有什么不同
类组件可以使用生命周期钩子函数,函数式组件需要通过hooks来模拟生命周期函数,类组件有state,而函数式组件需要使用hooks中的usestate来实现state,
一百三十七、flux思想
flux是单向数据流,用户访问view,view发出用户的action,dispatcher收到action,要求store进行相应的更新,store更新后,发出chengge事件,view收到chengge事件后,更新页面
一百三十八、redux
redux是一个应用数据流框架,主要是解决了组件间状态共享的问题,原理是集中式管理,主要有,action,store,reducer,view调用store的dispatch接收action传入store,reducer进行steta操作,view通过store提供的getstate获取最新的数据,
一百三十九、什么是jsx
jssx即jsxml,一种在react组件内部构建标签的类xml语法,jsx为react开发的一套语法糖,也是react的使用基础,react在不使用jsx的情况下一样可以工作,使用jsx可以提高组件的可读性。
一百四十、class组件有什么不同
生命周期臃肿,逻辑耦合
逻辑难以复用,通过继承解决,不支持多继承,通过高阶组件解决,会增加额外的组件嵌套,通过渲染属性解决,也会增加额外组件嵌套,层级臃肿
class存在this指向的问题,匿名函数解决,每次创建新的函数,子组件重复不必要渲染,bind解决,需要写很多逻辑状态无关的代码
一百四十一、git常用命名
git status仓库当前的状态
git log 显示当前分支的版本历史
git init 初始化仓库,编写project-name就在当前文件夹下建仓库
git add 提交到暂存区,如果dir是.,为添加当前目录的所有文件到暂存区,否则为指定目录下的所有文件及其文件下的文件
git commit - m 提交到本地仓库git branch 显示本地分支
git checkout -b 新建一个分支,并切换到该分支
git fetch 下载远程仓库的所有变动
git pull 取回远程仓库的变化,并与本地分支合并
git oush 长传本地指定分支到远程仓库,(一般先pull在push,如果合并不上就是看哪里冲突了,不要git push -f,会把人的提交代码覆盖掉,是不可逆的)
git blame检查这个文件是什么时候被什么人修改过
一百四十二、react和vue的区别
react是通过js来生成html,通过js才操作css,而vue是响应式的,用各自的处理方式,vue有单文件组件,可以把html、js和css写在一个文件中
react做的事情很少,很多都是交给社区去做,vue很多东西都是内置的,写起来方便一些
设计思想不同
改变数组和不改变原数组的方法
不会改变原来数组的有:
concat()—连接两个或更多的数组,并返回结果。
every()—检测数组元素的每个元素是否都符合条件。
some()—检测数组元素中是否有元素符合指定条件。
filter()—检测数组元素,并返回符合条件所有元素的数组。
indexOf()—搜索数组中的元素,并返回它所在的位置。
join()—把数组的所有元素放入一个字符串。
toString()—把数组转换为字符串,并返回结果。
lastIndexOf()—返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索。
map()—通过指定函数处理数组的每个元素,并返回处理后的数组。
slice()—选取数组的的一部分,并返回一个新数组。
valueOf()—返回数组对象的原始值。
会改变原来数组的有:
pop()—删除数组的最后一个元素并返回删除的元素。
push()—向数组的末尾添加一个或更多元素,并返回新的长度。
shift()—删除并返回数组的第一个元素。
unshift()—向数组的开头添加一个或更多元素,并返回新的长度。
reverse()—反转数组的元素顺序。
sort()—对数组的元素进行排序。
splice()—用于插入、删除或替换数组的元素。
数组扁平化
1. reduce
遍历数组每一项,若值为数组则递归遍历,否则concat。
function flatten(arr) {
return arr.reduce((result, item)=> {
return result.concat(Array.isArray(item) ? flatten(item) : item);
}, []);
}
reduce是数组的一种方法,它接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
reduce包含两个参数:回调函数,传给total的初始值
// 求数组的各项值相加的和:
arr.reduce((total, item)=> { // total为之前的计算结果,item为数组的各项值
return total + item;
}, 0);
2. toString & split
调用数组的toString方法,将数组变为字符串然后再用split分割还原为数组
function flatten(arr) {
return arr.toString().split(',').map(function(item) {
return Number(item);
})
}
因为split分割后形成的数组的每一项值为字符串,所以需要用一个map方法遍历数组将其每一项转换为数值型
3. join & split
和上面的toString一样,join也可以将数组转换为字符串
function flatten(arr) {
return arr.join(',').split(',').map(function(item) {
return parseInt(item);
})
}
4. 递归
递归的遍历每一项,若为数组则继续遍历,否则concat
[](javascript:void(0);)
function flatten(arr) {
var res = [];
arr.map(item => {
if(Array.isArray(item)) {
res = res.concat(flatten(item));
} else {
res.push(item);
}
});
return res;
}
[](javascript:void(0);)
5. 扩展运算符
es6的扩展运算符能将二维数组变为一维
[].concat(...[1, 2, 3, [4, 5]]); // [1, 2, 3, 4, 5]
根据这个结果我们可以做一个遍历,若arr中含有数组则使用一次扩展运算符,直至没有为止。
function flatten(arr) {
while(arr.some(item=>Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
filter。some、every
map()、filter()、some()、every()的共同点
map()、filter()、some()、every()中都提供一个回调函数,回调函数中有三个参数分别是数组元素,元素索引,原数组本身,并且这四个方法在使用的过程中都不会改变原数组。
map()
map()方法会遍历自身的所有元素,并且返回一个新的数组,该新数组是原本数组中的所有元素都调用一次方法中所提供的回调函数所处理后的结果
map() 不修改调用它的原数组本身(当然可以在 callback 执行时改变原数组)
demo如下:
// 将数组中的所有项值乘二
let arr = [1, 2, 3, 4];
let newArr = arr.map(item =>
item * 2
)
/*
let newArr = arr.map(function(num) {
return num * 2;
})
*/
console.log(newArr);// [2, 4, 6, 8]
filter()
filter()方法会返回一个新数组,该新数组的元素是符合回到函数中筛选条件的结果
filter()为数组中的每个元素调用一次 callback 函数,并利用所有使得回调函数返回 true 或等价于 true 的值的元素创建一个新数组;如果没有任何的项符合筛选的条件(false),那么filter()方法将返回一个空的数组
demo如下:
let arr = [11, 34, 5, 9, 20];
let newArr = arr.filter(item =>
item >= 10
)
/*
let newArr = arr.filter(function(item) {
return item >= 10;
})
*/
console.log(newArr); // [11, 34, 20]
some()
some()方法会返回一个Boolean类型的值,该值取决了数组中是否有元素满足给定的条件
some()为数组中的每一个元素执行一次回调函数,直到找到一个使得回调函数返回一个“真值”(即可转换为布尔值 true 的值),如果找到了这样一个值,some() 将会立即返回 true;否则,some() 返回 false
demo如下:
let arr = [10, 20, 40, 50, 60];
let flag = arr.some(item =>
item >= 50
}
/*
let flag = arr.some(function(item) {
return item >= 50;
})
*/
console.log(flag); // true
every()
every()方法会返回一个Boolean类型的值,该值取决了数组中是否所有的元素满足给定的条件
every()为数组中的每一个元素执行一次回调函数,如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测;如果所有的元素都满足给定的条件,那么将返回一个true
demo如下:
let arr = [1, 8, 19, 48, 10];
let flag = arr.every(item =>
item < 100
}
/*
let flag = arr.every(function(item) {
return itme < 100;
})
*/
console.log(flag); // true
为什么要使用函数式组件
函数式组件,即无状态,无法实例化,内部没有任何生命周期处理方法,非常轻量,因而渲染性能高,特别适合用来只依赖外部数据传递而变化的组件
1.类组件的性能消耗比较大,因为类组件需要创建类组件的实例,而且不能销毁。
2.函数式组件性能消耗小,因为函数式组件不需要创建实例,渲染的时候就执行一下,得到返回的react元素后就直接把中间量全部都销毁。
函数式组件是不能有状态的,但是现在有了react hooks,也可能有状态了。
为什么要使用虚拟dom
- 虚拟DOM不会进行排版与重绘操作
- 虚拟DOM进行频繁修改,然后一次性比较并修改真实DOM中需要改的部分(注意!),最后并在真实DOM中进行排版与重绘,减少过多DOM节点排版与重绘损耗
- 真实DOM频繁排版与重绘的效率是相当低的
- 虚拟DOM有效降低大面积(真实DOM节点)的重绘与排版,因为最终与真实DOM比较差异,可以只渲染局部(同2)
五十一、redux是怎么实现的
redux首先安装redux react-redux redux-thunk
接着创建store文件夹,store文件夹内创建index.js,作为暴露使用的文件
创建reducer文件夹和action文件夹,在这俩个文件夹都创建index.js根目录
然后再reducer的跟目录中,先声明const reducer,reducer内有俩个参数,一个是state,另外一个是
action,state定义变量,可以为数组或者对象,字符串
接着在使用箭头函数,使用switch,switch中传入相应的action.type,然后再case后面接自定义的方法,以及return相对应的操作,将多个操作方法完成后,defauit:return state,
接着抛出reducer
定义action文件下的跟文件
先声明action里面接方法的名称,使用函数传入dispatch方法,箭头函数,接着调用接口方法,或者直接用aixos.get或者fetch方法获取到调取的接口的响应结果
调用dispatch方法,传入type,以及从接口请求的入参payload来改变reducer里面的state内的变量,
或者直接调用方法传入固定的参数改变redcuer里面state的变量
接着到store的index去暴露
引用createstore,applymiddleware,combinereducer from‘ redux’
引用thunk from‘ redux-thunk’
接着引入reducer,当有多个reducer的时候,需要使用combinereducer去合并
接着用createstore去传入reducer以及applymiddleware(thunk),当有异步的操作的时候,必须使用applymiddleware(thunk)
然后抛出store
顶级的index.js需要去引入store以及{providder}prom ‘react-redux’
到渲染的区域使用providder标签,包裹引用的组件,同时需要store={store}
然后到展示页面
引入{connect}from ‘react-redux’
将底下抛出的组件名用connect包裹着