React作为现在前端开发领域的三大框架之一(React,Vue, Angular)广受前端同学的青睐,甚至会有一些刚步入IT行业的小白来说都会直接上手,今天我们就先来聊聊react的那些事~
- React的生命周期都有哪些?
首先我们先来看一下React的整体生命周期图
Constructor:是ES6对类的默认方法,通过new命令生成对象实例时自动调用该方法。并且,该方法是类中必须有的,如果没有定义,则会默认添加空的constructor()方法,当存在constructor的时候⚠️必须在constructor函数里面调用super方法。在constructor中 如果要使用this.props需要传入props,在super()被调用之前,子类是不能使用this的,在ES2015中,子类必须在constructor中调用super(),传递props给super()的原因则是便于(在子类中)能在constructor访问this.props
示例如下:Class TestComponent extends Component { constructor(props) { super(props) this.state = { list: this.props.list } } }
-
ComponentWillMount()组件挂载前
在组件挂载前调用且全局只调用一次,如果在这个钩子里可以setState,render后可以看到更新后的state,不会触发重复渲染,该生命周期可以发起异步请求并进行setState(React在V16.3以后便废弃该钩子函数,可以在组件声明的时候constructor函数里面对state进行初始化) -
render()渲染组件
render是一个React组件必须定义的生命周期,用来渲染DOM。⚠️不要在render里面修改state,会触发死循环导致栈溢出,render必须返回reactDOM -
componentDidMount()组件挂载后
在组件挂载完成后调用且全局只调用一次,可以在这里使用refs,获取真实DOM,该钩子内也可以发起异步请求并在异步请求中可以进行setState -
componentWillReceiveProps(nextProps)props即将变化之前
props发生变化以及父组件重新渲染时都会触发该生命周期,在该钩子内可以通过参数nextProps获取变化后的props参数,通过this.props访问之前的props,该生命周期内可以进行setState -
shouldComponentUpdate(nextProps, nextState)是否重新渲染
组件挂载之后,每次调用setState以后都会调用shouldComponentUpdate判断是否需要重新渲染组件,默认返回true,需要重新render,返回false则不触发重发渲染,在比较复杂的应用里,有一些数据的改变并不影响界面的展示,可以在这里做判断,优化渲染效率 -
componentWillUpdate(nextProps,nextState)
shouldComponentUpdate返回true或者调用forceUpdate之后,componentWillupdate会被调用,不能把在该钩子中setState,会触发重复循环(React v16.3后废弃该生命周期,可以用新的周期 getSnapshotBeforeUpdate ) -
componentDidUpdate()完成组件渲染
除了首次调用componentDidMount,其他render结束之后都是调用componentDidUpdate,该钩子内setState又可能会触发重复渲染,需要自行判断,否则会进入死循环 -
componentWillUnMount()组件即将被卸载
组件被卸载的时候调用,一般在componentDidMount里面注册的事件需要在这里面删除 -
React v16.3 新加入的生命周期 (转载)
react v16.3删掉以下三个生命周期
componentWillMount
componentWillReceiveProps
componentWillUpdate
新增两个生命周期
static getDerivedStateFromProps
getSnapshotBeforeUpdate
static getDerivedStateFromProps
触发时间:在组件构建之后(虚拟dom之后,实际dom挂载之前) ,以及每次获取新的props之后。
每次接收新的props之后都会返回一个对象作为新的state,返回null则说明不需要更新state.
配合componentDidUpdate,可以覆盖componentWillReceiveProps的所有用法class Example extends React.Component { static getDerivedStateFromProps(nextProps, prevState) { // 没错,这是一个static } }
getSnapshotBeforeUpdate
触发时间: update发生的时候,在render之后,在组件dom渲染之前。
返回一个值,作为componentDidUpdate的第三个参数。
配合componentDidUpdate, 可以覆盖componentWillUpdate的所有用法。
class Example extends React.Component { getSnapshotBeforeUpdate(prevProps, prevState) { // ... } }
-
-
Raect中key的作用是什么?
key是React用于追踪哪些列表中的元素被修改、被添加或者被移除的辅助标识render() { return ( <div> { this.state.todoItem.map((item, index) => { return <li key={index}>{item}</li> }) } </div> ) }
在开发的过程中,我们需要保证某个元素的key的在其同级元素中具有唯一性。在React Diff算法中React会借助元素的key值来判断该元素是最新被创建的还是被移动而来的,从而减少不必要的元素重新渲染。此外,React还需要借助Key值来判断元素与本地状态的关联关系,因此我们绝不可忽略转换函数中key的重要性
-
调用setState之后发生了什么?
在代码中调用setState函数之后,React会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation)。经过调和过程,React会以相对高效的方式根据新的状态构建React元素树并且着手重新渲染整个UI界面。在React得到元素树之后,React会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染。在差异计算算法中,React能够相对精确的知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。 -
React Diff原理,为什么虚拟DOM就可以提高性能
原理:把树形结构按照层级分解,只比较同级元素;给列表结构的每个单元添加唯一的key属性,方便比较;React只会匹配相同class的component(这里的class指的是组件的名字);合并操作,调用component的setState方法的时候,React将其标记为dirty,到每一个事件循环结束,React检查所有标记dirty的component重新绘制;选择性子树渲染,开发人员可以重写shouldComponentUpdate提高diff的性能
虚拟DOM:虚拟dom相当于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的dom操作,从而提高性能。用JavaScript对象结构标识DOM树的结构;然后用这个树构建一个真正的DOM树,插到文档当中当状态变更的时候,重新构造一课新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异把2所记录的差异应用到步骤1所构建的真正的DOM树上,视图就更新了 -
React中refs的作用是什么?
Refs是React提供给我们的安全访问DOM元素后者某个组件实例的句柄。我们可以为元素添加ref属性然后在回调函数中接受该元素在DOM树中的句柄,该值会作为回调函数的第一个参数返回:class CustomForm extends Component { handleSubmit = () => { console.log("Input Value: ", this.input.value) } render () { return ( <form onSubmit={this.handleSubmit}> <input type='text' ref={(input) => this.input = input} /> <button type='submit'>Submit</button> </form> ) } }
上述代码中的input域包含了一个ref属性,该属性声明的回调函数会接收input对应的DOM元素,我们将其绑定到this指针以便在其他的类函数中使用。另外值得一提的是,refs并不是类组件的专属,函数式组件同样能够利用必报暂存其值:
function CustomForm ({handleSubmit}) { let inputElement return ( <form onSubmit={() => handleSubmit(inputElement.value)}> <input type='text' ref={(input) => inputElement = input} /> <button type='submit'>Submit</button> </form> ) }
-
(组件的)状态state和属性props之间有何不同?
state是一种数据结构,用于组件挂载时所需数据的默认值。State可能会随着时间的推移而发生改变,但多数时候是作为用户事件行为的结果
props则是组件的配置。props由父组件传递给子组件,并且就子组件而言,props是可不变的。组件不能改变自身的props,但是可以把其子组件的props放在一起(统一管理)。Props也不仅仅是数据-回调函数也可以通过props传递 -
简述flux思想
Flux的最大特点就是数据的“单向流动”
a.用户访问view
b.View发出用户的Action
c.Dispatcher收到Action,要去store进行相应的更新
d.Store更新后,发出一个“change”事件
e.View收到“change”事件后,更新页面