根据官网了解到,React既有以下工具链:
Node.js构建服务端渲染网站,可使用Next.js
面向内容的静态网站,可使用Gatsby
以及更灵活的Neutrino、Parcel、Razzle
目前对React还不够熟练,因此现以简单了解为主。
元素是React应用的最小单位。
React元素一经创建就是不可变的(immutable),更新的唯一方法是重新创建元素并渲染;
尽管如此,React DOM会将当前元素与之前的进行比较,只做必要的更新。(重要且深刻)
设计目标:独立、可复用
React组件有两种形式:
纯函数不改变自己的传入参数,React组件必须保证props不被修改
要使用this.setState()方法来改变组件的state,也只有调用setState()修改state,组件才会重新渲染
为了提升性能,React会合并多次setState()请求,因此不能保证对state的改变会立即生效(批量推迟更新);
目前,在事件处理函数的内部,setState()是异步的,这种机制让应用的性能得到提升。
每次更新this.state都必然要调用一轮Update阶段的生命周期函数,这是存在性能消耗的,异步调用setState()就是为了将多次setState()的改变合并在一起,然后一次性更新state,节约性能。
但问题在哪呢?
实际我们经常会基于当前的this.state来更新state,但是this.state可能没有被更新,
这就会导致基于上一个state更新state的操作出现问题。可以参考下面的解决方法:
setState(updater, [callback])
updater:
(state, props) => {}
这里的state、props不同于this.state、this.props,它们保证是最新的,可以以此为基础,
更新this.state。该函数最后要返回一个对象,它会被浅层合并到最新的state中。
callback:
可传入回调函数,它在setState完成合并、重新渲染后触发,但也因此可以在componentDidUpdate()上实现一样的效果;
React生命周期的速查表
https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
React生命周期方法是由React主动调用的
render()是唯一一个必须被实现的生命周期方法
挂载:
constructor()
getDerivedStateFromProps() - 不常用
render()
更新:
shouldComponentUpdate() - 性能优化
getDerivedStateFromProps() - 不常用
卸载:
componentWillUnmount()
记录:
比如在此之前对refs进行操作,会导致错误
以下是一个例子:
shouldComponentUpdate(nextProps, nextState) {
if (this.props.color !== nextProps.color) {
return true;
}
if (this.state.count !== nextState.count) {
return true;
}
return false;
}
shouldComponentUpdate接受了两个参数,在这仅当“未来的”props||state不等于本来的时候,
才返回true、更新组件,从而当state、props发生改变而改变后值与原来相同时不进行重新渲染,
节省了性能。
React.PureComponent
它通过浅层比较props和state对象,实现了上述功能。
由于仅做浅层比较,因此不能检查深层的差别(比如做了某个数组中的push操作等)。
浅层比较带来的问题:
还记得const吗?const只保证一个变量其内存指向是不变的,如果改变了对象内部的属性,const也将无能为力,
因此const是浅层的“常量”;
在这里,PureComponent会有一样的情况,如果state、props中的某个属性是对象,那么只要它们的指向不变,
就不会引起组件的更新,从而导致问题。
PureComponent 结合 immutable.js
由于浅层比较只比较了指向,那么 immutable.js 就可以解决这个问题:
这是因为针对immutable对象的一切改变都将返回一个不同的指针,从而得以触发组件的更新。
React的数据是向下流动的,数据只能从父组件流向子组件;
父组件把state传给它的子组件,子组件在props中接收到数据;
但是,子组件要改变父组件的数据,只能调用父组件传入的方法*(下面马上提到),
父组件state修改后,子组件的props随着改变。
区别: