1、props和state相同点和不同点?render方法在哪些情况下会执行?
props是一个从外部传进组件的参数,由于React具有单向数据流的特性,所以他的主要作用是从父组件向子组件中传递数据,它是不可改变的,如果想要改变它,只能通过外部组件传入新的props来重新渲染子组件,否则子组件的props和展示形式不会改变,props除了可以传字符串,数字,还可以传递对象,数组甚至是回调函数
state主要作用是用于组件保存,控制及修改自己的状态,它只能在constructor中初始化,state是可以被改变的,state放改动的一些属性,比如点击选中,再点击取消,类似这种属性就放入带state中,注意:没有state的叫做无状态组件,多用props少用state,多写无状态组件,注意:修改state的值时,必须通过调用setState方法,当我们调用this.setState方法时,React会更新组件的数据状态,并且重新调用render方法
render方法在类组件抵用setState修改状态时;函数组件通过useState hook或者通过useState修改状态时;
当我们的数据发生改变render方法就会触发
2、shouldComponentUpdate有什么作用?
shouldComponentUpdate 函数是 React 中的一个生命周期函数,
用于在更新组件前检查数据是否有变化,从而决定是否重新渲染组件
shouldComponentUpdate 函数的作用:
(1)提升组件性能:当组件在接收到新的 props 和 state 时,可以通过shouldComponentUpdate 判断是否需要重新渲染,减少不必要的渲染(2)允许控制: React通过此函数允许开发者控制组件是否重新渲染,能够提高开发效率,实施预期的操作。
3、说说React中的虚拟dom?在虚拟dom计算的时候diff和key之间有什么关系?
虚拟dom本质上是js对象,是真实dom的抽象,状态变更时记录新旧dom树的差异,
最后把差异更新到真实dom中去,react虚拟dom是在浏览器端用js实现了一套dom接口,
基于react进行开发时所有的dom构造都是通过虚拟dom进行,
当数据发生变化是,react重新构建整个dom树,
然后react将当前整个dom树和上一次的dom树进行对比,得到dom结构的区别
4、react新出来两个钩子函数是什么?和删掉的will系列有什么区别?
getDerivedStateFromProps
getSnapshotBeforeUpdate
componentWillReceiveProps实际行为与命名并不相符,由于不稳定性已由getDerivedStateFromProps代替;
而componentWillUpdate同等理由被getSnapshotBeforeUpdate代替
5、React的props.children使用map函数来遍历会收到异常显示,为什么?应该如何遍历?
在reactJS 中 props.children 不一定是数组,
有三种可能 :
1当前组件没有子节点数据类型就是undefined,
2有一个子节点数据类型就是object 。
3 有多个子节点的时候才会是array ,只有在多个节点的时候才可以直接调用map方法,react资深提供了一个react.children.map()方法,可以安全遍历子节点对象。
6、React组件之间如何通信?
父组件向子组件传递,父组件在调用子组件的时候,在子组件标签内传递参数,子组件通过props属性就能接收父组件传递过来的参数
子传父,父组件向子组件传一个函数,然后通过这个函数的回调,拿到子组件传过来的值
兄弟组件,父组件最为中间层实现数据的互通,通过父组件传递
父组件向后代组件传递,使用context提供组件之间通讯的一种方式,通过使用React.createContext创建context
非关系组件传递,将数据进行一个全局资源管理,实现通信
7、谈谈你对immutable.js的理解?
Immutable,不可改变的,指一旦创建,就不能再被更改的数据
对
Immutable
对象的任何修改或添加删除操作都会返回一个新的Immutable
对象
Immutable
实现的原理是Persistent Data Structure
(持久化数据结构):
- 用一种数据结构来保存数据
- 当数据被修改时,会返回一个对象,但是新的对象会尽可能的利用之前的数据结构而不会对内存造成浪费
也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变,同时为了避免
deepCopy
把所有节点都复制一遍带来的性能损耗,Immutable
使用了Structural Sharing
(结构共享)如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享
8、redux本来是同步的,为什么它能执行异步代码?实现原理是什么?中间件的 实现原理是什么?
用redux执行同步的时候,都是先发起一个dispatch(actionCreator())
1.先在actionCreator()中生成一个action对象。
2.由dispatch方法将action传到reducer。
3.reducer中计算新state
4.新state保存到store中
5.因为容器组件将state作为props传给展示组件,state更新后,展示组件渲染更新的部分(因为props更新了)
app中的各部分都有纯粹而限定的职责,reducer只负责计算新state、P组件只负责渲染、C组件只负责获取update后的state和disptach方法传递给P组件。
而异步操作,同样被归类为一种action(action可能会改变state)。所以异步操作的代码被放到action creator的返回值里,但是dispatch方法只能接收js对象
9、redux中同步action与异步action最大的区别是什么?
同步action:执行了dispatch函数之后,对应的reducer纯函数立即得到执行,reducer执行完了之后,state立即就改变了,此时用store.getState函数,取到的是最新的state值;
异步action:原则上redux并没有提供异步action的处理方案,异步的action需要依赖第三方的中间件解决(如redux-thunk),dispatch了一个异步action(本质上是dispatch的一个函数)之后,目标state并不会立即响应,而是要看异步函数内部的逻辑,来决定state什么时候响应
10、redux-saga和redux-thunk的区别与使用场景?
redux-thunk通过对dispatch进行升级,让dispatch可以接收函数
redux-thunk可以将异步逻辑放在actionCreator里面
redux-saga和redux-thunk作用类似
store action的中间
redux-saga提供许多api put takeEvey takeLast ..
redux-thunk 只是让dispatch 可以接收函数
11、在使用redux过程中,如何防止定义的action-type的常量重复?
ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。
Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象
Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分
12、CDN的特点及意义?
CDN
意为内容分发网络,是基于现有网络的智能虚拟网络,分布在世界各地的边缘服务器上。避免互联网上可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输更快更稳定
CDN 的特点
- 本地缓存加速
- 镜像服务
- 远程加速
- 带宽优化
- 集群抗攻击
13、为什么for循环比forEach性能高?
foreach的性能要比for要高;
因为for循环要进行一个array.GetLength来获取数组最大下标。
当然只是相对的
1、如果只是读数据,选择foreach
2、如果只是写数据,选择for
3、for循环遍历的效率是低于foreach循环遍历
for循环在外部做count和在条件中做count相比较,第一种效率更高(for每次循环的时候都要去判断是否符合循环条件)
4、foreach 依赖 IEnumerable.
第一次 var a in GetList() 时 调用 GetEnumerator 返回第一个对象 并 赋给a
以后每次再执行 var a in GetList() 的时候 调用 MoveNext.直到循环结束
期间GetList()方法只执行一次
14、说说你对@reduxjs/toolkit的理解?和react-redux有什么区别?
reduxjs/toolkit:
Redux 官方强烈推荐,开箱即用的一个高效的 Redux 开发工具集。它旨在成为标准的 Redux 逻辑开发模式,使用 Redux Toolkit 都可以优化你的代码,使其更可维护
react-redux:
react官方推出的redux绑定库,react-redux将所有组件分为两大类:UI组件和容器组件,其中所有容器组件包裹着UI组件,构成父子关系。容器组件负责和redux交互,里面使用redux API函数,UI组件负责页面渲染,不使用任何redux API。容器组件会给UI组件传递redux中保存对的状态和操作状态的方法
15、React render方法的原理,在什么时候会触发?
原理:
在类组件中render函数指的就是render方法;而在函数组件中,指的就是整个函数组件
render函数中的jsx语句会被编译成我们熟悉的js代码,在render过程中,react将新调用的render函数返回的树与旧版本的树进行比较,这一步是决定如何更新 DOM 的必要步骤,然后进行 diff 比较,更新dom树
触发时机:
类组件调用 setState 修改状态
函数组件通过useState hook修改状态
一旦执行了setState就会执行render方法,useState 会判断当前值有无发生改变确定是否执行
render方法,一旦父组件发生渲染,子组件也会渲染
16、![] == ![],![] == [],结果是什么?为什么?
①、根据运算符优先级 ,! 的优先级是大于 == 的,所以先会执行 ![]
!可将变量转换成boolean类型,null、undefined、NaN以及空字符串('')取反都为true,其余都为false。
所以 ! [] 运算后的结果就是 false
也就是 [] == ! [] 相当于 [] == false
②、根据上面提到的规则(如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false转换为0,而true转换为1),则需要把 false 转成 0
也就是 [] == ! [] 相当于 [] == false 相当于 [] == 0
③、根据上面提到的规则(如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较,如果对象没有valueOf()方法,则调用 toString())
而对于空数组,[].toString() -> '' (返回的是空字符串)
也就是 [] == 0 相当于 '' == 0
④、根据上面提到的规则(如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值)
Number('') -> 返回的是 0
相当于 0 == 0 自然就返回 true了
17、什么是闭包,应用场景是什么?
可以访问外部函数中的变量的内部函数,
在js中只有函数内部的子函数才能读取局部变量,
闭包就是将函数内部和函数外部连接起来的桥梁,让外部访问函数内部变量,
局部变量常驻在内存中,可以避免使用全局变量,防止全局变量污染,
会造成内存泄漏,每次执行外部函数的时候,
外部函数的引用地址不同,都会创建一个新的地址
应用场景:
函数嵌套
内部函数中引用了外部函数的变量
将内部函数作为返回值返回
18、谈谈你是如何做移动端适配的?
px + viewport适配
rem布局
。CSS3媒体查询适配
。基于设计图的rem布局
。基于屏幕百分比的rem布局
。小程序的rpx布局vw布局
。通过媒体查询的方式即CSS3的meida queries
。以天猫首页为代表的flex弹性布局
。以淘宝首页为代表的rem+viewport缩放
。rem方式
19、移动端1像素的解决方案?
使用伪类缩放
使用 -webkit-min-device-pixel-ratio
使用box-shadow模拟
使用图片
20、弹性盒中的缩放机制是怎样的?
弹性盒中的项目设置flex-grow属性定义项目的放大比例,默认值为0,值越大,放大越厉害,且不支持负值;而flex-shrink属性定义项目的缩小比例,默认值为1,数值越大,缩小越厉害,同样不支持负值;
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间,浏览器根据这个属性,计算主轴是否有多余空间。他的默认值为auto,也就是项目的本来大小。
注意:它可以设为跟width或height属性一样的值,比如给具体的像素值,则项目将占据固定空间。