最近工作一直用的class组件,很久没碰函数式组件了,现在做个总结,也算是温习了。打算这波回顾之后就用函数式组件。
先说why not class
class组件有他的优势,比如模板傻瓜式,很容易上手,生命周期也帮我们提前内置了,很省心。但其实还存在很多不足
-
状态逻辑难复用: 在组件之间复用状态逻辑很难,可能要用到 render props (渲染属性)或者 HOC(高阶组件),但无论是渲染属性,还是高阶组件,都会在原先的组件外包裹一层父容器(一般都是 div 元素),导致层级冗余
-
趋向复杂难以维护:
在生命周期函数中混杂不相干的逻辑(如:在 componentDidMount 中注册事件以及其他的逻辑,在 componentWillUnmount 中卸载事件,这样分散不集中的写法,很容易写出 bug )
类组件中到处都是对状态的访问和处理,导致组件难以拆分成更小的组件
- this 指向问题:父组件给子组件传递函数时,必须绑定 this
那么这些不足可以解决吗?可以,用函数式组件
const Hello = (props) => {
return <div>{props.message}</div>
}
复制代码
但是呢,函数式组件相比class组件缺了state和生命周期。
神说要有光,这世间便有了光
react 16.8.0 推出了 hooks api ,其中 useState 解决了没有 state 的问题
const App = props => {
const [n,setN] = useState(0) //n是读,setN是写,0 是 n 的初始值
const onClick = () => {
setN(n + 1)
}
return (
<div>
{n}
<button onClick = {onClick} >+1</button>
</div>
)
}
复制代码
hooks api 中的 useEffect 解决了没有生命周期的问题
- 函数组件执行的时候就相当于 constructor
- 模拟 componentDidMount
useEffect(()=>{ console.log('第一次渲染') },[])
复制代码
- 模拟 componentDidUpdate
useEffect(()=>{ console.log('任意属性变更')})
useEffect(()=>{ console.log('n 变了')}, [n])
复制代码
- 模拟 componentWillUnmount
useEffect(()=>{
console.log('第一次渲染')
return ()=>{
console.log('组件要挂了')
}
})
复制代码
- 模拟 shouldComponentUpdate
React.memo 和 useMemo 解决
- 模拟 render
函数组件的返回值就是 render 的返回值
所以函数式组件不仅可以避免 class 组件的很多不足,还更加灵活自由,这么看来是个很好的替代品
下一节打算好好总结下各个hooks api
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END