"小和山的菜鸟们",为前端开发者提供技术相关资讯以及系列基础文章。为更好的用户体验,请您移至咱们官网小和山的菜鸟们 ( xhs-rookies.com/ ) 进行学习,及时获取最新文章。html
"Code tailor" ,若是您对咱们文章感兴趣、或是想提一些建议,微信关注 “小和山的菜鸟们” 公众号,与咱们取的联系,您也能够在微信上观看咱们的文章。每个建议或是赞同都是对咱们极大的鼓励!前端
react
的核心思想就是,将一个页面拆成一堆独立的,可复用的组件,而且用自上而下的单向数据流的形式将这些组件串联起来。但若是你在大型的工做项目中用 react
,你会发现你的项目中实际上不少 react
组件冗长且难以复用。特别是那些 class
的组件,它们自己包含了 state
,很难进行复用。node
官方推荐解决方案react
prop
来传递须要动态渲染的 nodes
或组件.以下面的代码能够看到咱们的Provider
组件包含了全部跟状态相关的代码,而 MyComponent
组件则能够是一个单纯的展现型组件,这样一来Provider
就能够单独复用了import MyComponent from 'components/myComponent'
class Provider extends React.Component {
constructor(props) {
super(props)
this.state = { target: 'MyComponent' }
}
render() {
return <div>{this.props.render(this.state)}</div>
}
}
<Provider render={(data) => <MyComponent target={data.target} />} />
复制代码
这个模式叫 Render-Props
.web
固然通常状况下,都会被写成下面这样的方式:ajax
<Provider>{(data) => <Cat target={data.target} />}</Provider>
复制代码
withUser
函数就是一个高阶组件,它返回了一个新的组件,这个组件具备了它提供的获取用户信息的功能。const withUser = (WrappedComponent) => {
const user = localStorage.getItem('user')
return (props) => <WrappedComponent user={user} {...props} />
}
const UserPage = (props) => (
<div class="user-page"> <p>I'm the user, {props.user}!</p> </div>
)
export default withUser(UserPage)
复制代码
以上这两种模式看上去都挺不错的,不少库也运用了这样的模式,就像咱们经常使用的 React-router
库。可是这两种模式,会增长代码的层级关系。为了表现的明显,能够安装打开 React Devtools 看看代码的组件嵌套,会发现嵌套次数太多太多。chrome
而若是咱们使用 hooks
,那就会简洁不少,没有多余的层级嵌套。把各类想要的功能写成一个一个可复用的自定义 hook
,当你的组件想用什么功能时,直接在组件里调用这个 hook
便可。浏览器
咱们一般但愿一个函数只作一件事情,但咱们的生命周期钩子函数里一般同时作了不少事情。好比咱们须要在 componentDidMount
中发起请求获取数据,绑定一些事件监听等等。同时,有时候咱们还须要在 componentDidUpdate
作一遍一样的事情。缓存
当咱们的这个页面或者这个组件,变得复杂的时候,里面的内容就会变多,逻辑的清晰度就会降低。微信
父组件给子组件传递函数时, 必须绑定 this
react
中的组件四种绑定 this
方法的区别class App extends React.Component<any, any> {
handleClick2
constructor(props) {
super(props)
this.state = {
num: 1,
title: ' react study',
}
this.handleClick2 = this.handleClick1.bind(this)
}
handleClick1() {
this.setState({
num: this.state.num + 1,
})
}
handleClick3 = () => {
this.setState({
num: this.state.num + 1,
})
}
render() {
return (
<div> <h2>Ann, {this.state.num}</h2> <button onClick={this.handleClick2}>btn1</button> <button onClick={this.handleClick1.bind(this)}>btn2</button> <button onClick={() => this.handleClick1()}>btn3</button> <button onClick={this.handleClick3}>btn4</button> </div>
)
}
}
复制代码
this
,那么每次父组件刷新的时候,若是传递给子组件其余的 props
值不变,那么子组件就不会刷新render()
函数里面绑定 this
:由于 bind
函数会返回一个新的函数,因此每次父组件刷新时,都会从新生成一个函数,即便父组件传递给子组件其余的 props
值不变,子组件每次都会刷新;()=>{}
箭头函数:父组件刷新的时候,即便两个箭头函数的函数体是同样的,都会生成一个新的箭头函数,因此子组件每次都会刷新;综上所述,若是不注意的话,很容易写成第三种写法,致使性能上有所损耗
能优化类组件存在问题
能在无需修改组件结构的状况下复用状态逻辑(**自定义 Hooks **)
能将组件中相互关联的部分拆分红更小的函数(好比设置订阅或请求数据)
反作用的关注点分离:反作用指那些没有发生在数据向视图转换过程当中的逻辑,如 ajax
请求、访问原生dom
元素、本地持久化缓存、绑定/解绑事件、添加订阅、设置定时器、记录日志等。以往这些反作用都是写在类组件生命周期函数中的。而 useEffect
在所有渲染完毕后才会执行,useLayoutEffect
会在浏览器 layout
以后,painting
以前执行。
如今,咱们对 hooks
已经有了一个大概的了解。
那么以后就开始咱们的基础 hooks
教程了。
在 hooks
系列中,咱们主要介绍四个项目中经常使用的钩子:useState、useEffect、useRefs、useCallback.
若是大家想要了解一些其余钩子函数(useContext 、useReducer 、 useMemo 、 useImperativeMethods 、useMutationEffect、 useLayoutEffect),能够去官网查看。
在下节中,咱们将为你们介绍 useState
,敬请期待!