乐趣区

关于前端:hooks-系列一简介

快来退出咱们吧!

“ 小和山的菜鸟们 ”,为前端开发者提供技术相干资讯以及系列根底文章。为更好的用户体验,请您移至咱们官网小和山的菜鸟们 (https://xhs-rookies.com/) 进行学习,及时获取最新文章。

“Code tailor”,如果您对咱们文章感兴趣、或是想提一些倡议,微信关注 “小和山的菜鸟们” 公众号,与咱们取的分割,您也能够在微信上观看咱们的文章。每一个倡议或是同意都是对咱们极大的激励!

咱们为什么要学 hooks

React-Hooks 简介

react 为什么要有一个 hooks?

1. 有状态的类组件的复用太麻烦

react 的核心思想就是,将一个页面拆成一堆独立的,可复用的组件,并且用自上而下的单向数据流的模式将这些组件串联起来。但如果你在大型的工作我的项目中用 react,你会发现你的我的项目中实际上很多 react 组件简短且难以复用。特地是那些 class 的组件,它们自身蕴含了 state,很难进行复用。

官网举荐解决方案

  • 渲染属性 – 应用一个值为函数的 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 .

当然个别状况下,都会被写成上面这样的形式:

<Provider>{(data) => <Cat target={data.target} />}</Provider>
  • HOC 高阶组件 – 一个函数承受一个组件作为参数,通过一系列加工后,最初返回一个新的组件. 看上面的代码示例,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 看看代码的组件嵌套,会发现嵌套次数太多太多。

而如果咱们应用 hooks,那就会简洁很多,没有多余的层级嵌套。把各种想要的性能写成一个一个可复用的自定义 hook,当你的组件想用什么性能时,间接在组件里调用这个 hook 即可。

2. 生命周期函数外面逻辑比较复杂

咱们通常心愿一个函数只做一件事件,但咱们的生命周期钩子函数里通常同时做了很多事件。比方咱们须要在 componentDidMount 中发动申请获取数据,绑定一些事件监听等等。同时,有时候咱们还须要在 componentDidUpdate 做一遍同样的事件。

当咱们的这个页面或者这个组件,变得复杂的时候,外面的内容就会变多,逻辑的清晰度就会降落。

3.class 中的 this 指向问题

父组件给子组件传递函数时,必须绑定 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 长处

  • 能优化类组件存在问题
  • 能在无需批改组件构造的状况下复用状态逻辑(自定义 Hooks
  • 能将组件中互相关联的局部拆分成更小的函数(比方设置订阅或申请数据)
  • 副作用的关注点拆散 副作用指那些没有产生在数据向视图转换过程中的逻辑,如 ajax 申请、拜访原生dom 元素、本地长久化缓存、绑定 / 解绑事件、增加订阅、设置定时器、记录日志等。以往这些副作用都是写在类组件生命周期函数中的。而 useEffect 在全副渲染结束后才会执行,useLayoutEffect 会在浏览器 layout 之后,painting 之前执行。

小结

当初,咱们对 hooks 曾经有了一个大略的理解。

那么之后就开始咱们的根底 hooks 教程了。

hooks 系列中,咱们次要介绍四个我的项目中罕用的钩子:useStateuseEffectuseRefsuseCallback.

如果你们想要理解一些其余钩子函数(useContextuseReduceruseMemouseImperativeMethodsuseMutationEffectuseLayoutEffect),能够去官网查看。

下节预报

在下节中,咱们将为大家介绍 useState,敬请期待!

退出移动版