react生命周期有哪些
组件载入阶段:
componentWillMount:组件即将被装载、渲染到页面上,只调用1次
componentDidMount:组件真正在被装载之后,这里可以拿到真实DOM执行操作,只调用1次
运行中状态:
componentWillReceiveProps(nextProps):组件将要接收到新属性的时候调用,在这时setState不会触发额外的render,因为此时已经有一次来自父组件引发的render了。
shouldComponentUpdate:组件接受到新属性或者新状态的时候(返回 false,接收数据后不更新,阻止 render ,后面的函数不会继续执行)
这个方法用来判断是否需要调用 render 方法重绘 dom。
因为 dom 的描绘非常消耗性能,如果我们能在这个方法中能够写出更优化的 dom diff 算法,可以极大的提高性能。
componentWillUpdate:组件即将更新不能修改属性和状态
componentDidUpdate:组件已经更新
销毁阶段:
componentWillUnmount:组件即将销毁,这时候可以销毁绑定的事件监听或者定时器什么的。
有些好像把render也算进生命周期了:
render:组件在这里生成虚拟的 DOM 节点
https://www.jianshu.com/p/b331d0e4b398
为什么不能用数组下标来作为react组件中的key?
react 使用diff算法,使用key来做同级比对。如果使用数组下标作为key,有以下情况:
在数组头部或中部插入或删除元素: 所有key对应的节点的值发生更改,进行重新渲染。造成性能损耗
而如果使用数组中唯一值来作为key:不管是在何处插入或删除节点,其他key对应的节点的值未发生更改,只需插入或删除操作的数组节点。
react的diff算法是怎么完成的
- 把树形结构按照层级分解,只比较同级元素。
- 通过给列表结构的每个单元添加的唯一 key值进行区分同层次的子节点的比较。
- React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)
- 合并操作,调用 component 的 setState 方法的时候, React 将其标记为 dirty.
到每一个事件循环结束, React 检查所有标记 dirty 的 component 重新绘制。 - 选择性渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性能。
https://www.jianshu.com/p/3ba0822018cf
react虚拟DOM实现原理,以及为什么虚拟 dom 会提高性能
- 用 js对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中。
- 当状态变更的时候,重新构造一棵新的对象树。然后对比新旧虚拟DOM树,记录两棵树差异。
- 把 2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。
原因:虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法减少了对真实DOM的操作次数,从而提高性能。
react怎么从虚拟dom中拿出真实dom
Refs 是 React 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄。
我们可以为元素添加 ref 属性然后在回调函数中接受该元素在 DOM 树中的句柄,该值会作为回调函数的第一个参数返回。或者ref可以传字符串。
例如:<input ref=((input)=>{return this.name=input}) />
, this.name.value取值
或者 <input ref="name" />
,this.refs.name取值
React中的props和state的用法
- state 是一种数据结构,用于组件挂载时所需数据的默认值。state 可能会随着时间的推移而发生突变,但多数时候是作为用户事件行为的结果。
- props则是组件的配置。props 由父组件传递给子组件,并且就子组件而言,props 是不可变的(immutable)。
react组件之间如何通信
父子:父传子:props; 子传父:子调用父组件中的函数并传参;
兄弟:利用redux实现。
react的setState的原理及用法
原理:
当调用setState时,它并不会立即改变,而是会把要修改的状态放入一个任务队列,等到事件循环结束时,再合并指更新。
因此,setState有 异步,合并更新更新两个特性。
Batch Update:https://zhuanlan.zhihu.com/p/28532725
使用:
1.最常见的用法就是传入一个对象。
1 | this.setState({ |
2.还可以接收一个函数
1 | this.setState((prevState,props)=>{ |
3.因为setState是异步的,所以它还可以接收第二个参数,一个回调函数
1 | this.setState({count:2},()=>{ |
setState为什么是异步的
https://segmentfault.com/a/1190000013040438
- 保证内部的一致性
因为props是要等到父组件渲染过后才能拿到,也就是不能同步更新,state出于统一性设成异步更新。 - 性能优化
举例说你正在一个聊天窗口输入,如果来了一条新消息又要render,那就会阻塞你的当前操作,导致延迟什么的。 - 支持state在幕后渲染
异步可以使state在幕后更新,而不影响你当前旧的页面的交互,提升用户体验。
详情可以点击上面的参考链接,写的很详细的。
另外:setstate在原生事件,setTimeout,setInterval,promise等异步操作中,state会同步更新。
https://segmentfault.com/a/1190000014131698
react的优势以及特点
优势:
- 实现对虚拟DOM的操作,使得它速度快,提高了Web性能。
- 组件化,模块化。react里每一个模块都是一个组件,组件化开发,可维护性高。
- 单向数据流,比较有序,有便于管理,它随着React视图库的开发而被Facebook概念化。
- 跨浏览器兼容:虚拟DOM帮助我们解决了跨浏览器问题,它为我们提供了标准化的API,甚至在IE8中都是没问题的。
不足:
- react中只是MVC模式的View部分,要依赖引入很多其他模块开发。、
- 当父组件进行重新渲染操作时,即使子组件的props或state没有做出任何改变,也会同样进行重新渲染。
特点:
- 声明式设计:React采用声明范式,可以轻松描述应用。
- 高效:React通过对DOM的模拟,最大限度地减少与DOM的交互。
- 灵活:React可以与已知的库或框架很好地配合。
React如何性能优化
充分利用shouldComponentUpdate函数,不过这需要你的组件尽量最小化,如果当前组件数据过于复杂,其实是很难优化的。
给你的DOM遍历上加上唯一的key,注意尽量不要用index,因为如果你新DOM中删了某一个节点,它会重新排列index,
那跟原来同层级一比就都会完全不一样,而重新渲染了,所以最好使用id值什么的作key值。能用const声明的就用const。
DOM里少用箭头函数,当然其实要传参时也还是得用。再者,函数bind尽量写在constructor,避免每次render重新bind。
减少对真实DOM的操作。
如果是用webpack搭建环境的话,当一个包过大加载过慢时,可分打成多个包来优化。
react与vue的对比
相同点:
- 都用虚拟DOM实现快速渲染
- 我觉得父子,兄弟通信这些都挺像的,也都有自己的状态管理器:react=>redux, vue=>vuex
- 都是轻量级框架
- 现在vue也在渐渐吸收react中的一些语法,比如JSX语法,类式声明写法等
不同点:
- React属于单向数据流——MVC模式,vue则属于双向——MVVM模式。
- react兼容性比vue好,vue不兼容IE8.
- react采用JSX语法,vue采用的则是html模板语法。
- vue的css可以有组件的私有作用域,react则没有。
- react比vue好的另一点是,它是团队维护,而vue属于个人,一般来说,大型项目更倾向于react,小型则用vue,当然这也不是绝对。
Redux的实现流程
用户页面行为触发一个Action,然后,Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action。Reducer 会返回新的 State 。每当state更新之后,view会根据state触发重新渲染。
react-redux的实现原理
Redux作为一个通用模块,主要还是用来处理应用中state的变更,通过react-redux做连接,可以在React+Redux的项目中将两者结合的更好。
react-redux是一个轻量级的封装库,它主要通过两个核心方法实现:
Provider:从最外部封装了整个应用,并向connect模块传递store。
Connect:
1、包装原组件,将state和action通过props的方式传入到原组件内部。
2、监听store tree变化,使其包装的原组件可以响应state变化