Open evantianx opened 7 years ago
文中提到几个点:
关于 React 大型项目的目录组织方式(按照特性而非文件类型来组织),值得一试
setState()
setState()
并非即时更新,为了保证性能,React 会延时然后根据反馈更新。因此若要获得更新后的状态,有两种方法:
componentDidUpdate()
setState(updater, callback)
constructor(props)
React.Component
创建子类时,若需要初始化 state 或绑定某些事件时,可以用 constructor(props)
来完成。
注意: 若使用到 this.props()
则需要在 constructor(props)
开头声明 super(props)
,否则 this.props
会为 undefined。
初始化 state ,赋给 this.state
值即可。
constructor(props) {
super(props);
this.state = {
loading: true
}
}
componentWillMount()
挂载组件发生前调用。
建议不要在其中添加副作用或者订阅,将这些添加入 componentDidMount()
由于是在 render()
前调用,所以在该方法中同步调用 setState()
并不会引起额外的重渲染。但是通常情况下建议在 constructor()
中调用 setState()
。
componentDidMount()
顾名思义,在组件挂载之后立即调用。
此时 DOM 节点已经创建完毕,因此任何需要依靠 DOM 的初始化工作应该在该方法中进行。同时也是实例化网络请求以及订阅等的绝佳之处。
在该方法中调用 setState()
会引起额外的渲染。但是可以保证虽然 render()
会被调用两次,用户不会看到中间的状态(TODO: how?)。注意这样通常会引起性能问题。
某些情况下不可避免要在 componentDidMount()
中调用 setState()
对 DOM 节点进行操作,如弹窗,提示框等。
shouldComponentUpdate(nextProps, nextState)
判断组件输出是否受当前 state 或 props 变化的影响。默认情况下返回 true,任何状态的变化都会引起组件的 re-render。 若返回 false,组件将不会再调用
componentWillUpdate()
、render()
、componentDidUpdate()
这三个方法。
调用时间:
当接收到新的 props 或者 state 时调用,且该调用发生在 render()
之前。
若为初次渲染或者调用了forceUpdate()
,则该方法不会被调用。
对子组件 re-render 的影响:
返回 false 不会阻止状态发生变化的子组件的 re-render。
React.PureComponent
对 shouldComponentUpdate(nextProps, nextState)
的些微实现,之所以说是些微实现,是因为它在比较状态变化时只对 state 和 props 进行了浅比较。
比较
官方不建议在 shouldComponentUpdate()
中进行深比较,会引起性能问题。
componentWillReceiveProps(nextProps)
在已挂载组件接收到新的 props 时调用。 在挂载组件时不会调用
componentWillReceiveProps(nextProps)
,该方法只在 props 更新时调用。
注意:当 props 未发生改变时,React 也可能调用该方法,如父组件引起子组件 re-render 时。故一定要保证比较当前值和传过来的值。
componentWillUpdate(nextProps, nextState)
在
render()
之前调用。在首次渲染时不被调用。
注意:不能在 componentWillUpdate()
中调用 this.setState()
方法或者其他会引起更新的事件。
componentDidUpdate(prevProps, prevState)
在更新之后立即调用。首次渲染时不被调用。
主要用于组件更新后操作 DOM或者网络请求。
componentWillUnmount()
组件卸载或者销毁时调用。
一般用来清理在 componentDidMount()
中设置的定时器,网络请求或订阅等。
componentDidCatch(error, info)
React 16 中的新特性,参见 Error Handling in React 16
之前工作目录一般都是按照文件类型划分,如 actions、reducers 等。这样在开发某个特性的时候需要翻找相对应的目录,然后创建相对应文件,很麻烦。
依照特性划分,则会让你更专注于写代码,debugging 或者 refactoring 更加 ez。
The Anatomy Of A React & Redux Module (Applying The Three Rules) Additional Guidelines For (Redux) Project Structure
若要在事件回调中使用 this 来获取到组件实例:
class Login extends React.Component {
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this)
}
onSubmit = () => {
// do something
}
render() {
return (
<Button onClick={this.onSubmit}>Submit</Button>
)
}
}
为什么要进行这样的绑定?
This is why we need to bind event handlers in Class Components in React
主要原因就在于:
const a = 2
const obj = {
a: 1,
sayA() {
console.log(this.a)
}
}
const sayA = obj.sayA() // 1
const sayAOtherWay = obj.sayA
sayAOtherWay() // 2 这就是 React 组件中调用事件回调的方式
而在 React 组件中不进行 bind
的 this
指向为 undefined
的原因在于:
The bodies of class declarations and class expressions are executed in strict mode, that is the constructor, static and prototype methods. Getter and setter functions are executed in strict mode.
React 组件解耦要点
参考文章:
分离
render()
但是上述方法只是分离了组件组装位置,其他属性仍然存在耦合,我们要彻底解耦的话,可以使用功能组件分离: