@Shel
2017-07-24T03:13:59.000000Z
字数 2118
阅读 786
react
javascript
如果一个组件的渲染只依赖于外界传入的props
和它自己的state
,而并不依赖于外界的任何数据,它给我们的感觉就如同纯函数一样,给什么,渲染什么,这种组件的复用性最强,别人使用的时候根本不担心任何事情,只要看propTypes
它能接受什么参数,然后把参数传进去控制它就行了。
我们把这种组件叫做Pure Compoent
,因为它就像纯函数一样,可预测性非常强,对props
以外的数据零依赖,也不产生副作用。这种组件也叫Dumb Component
,因为它们呆呆的,让它干啥就干啥。
也许你曾经听过高阶函数或者类似的听起来有点吓人的名词。程序员之间聊天偶尔蹦出一两个深奥的名词是再正常不过的事。但在这里,我想说的是,那些听起来玄而又玄的东西所代表的东西其实往往很简单。在这里的高阶组件也是一样。
高阶组件就是一个函数,传给它一个组件,它返回一个新的组件。这个新的组件会使用传入的组件作为子组件。
请千万牢记,高阶组件不是组件,而是函数。
高阶组件的作用其实就是为了组件之间的代码复用。组件可能有着某些相同的逻辑,把这些逻辑抽离出来,放到高阶组件中进行复用。高阶组件内部的包装组件和被包装组件之间通过 props
传递数据。
它其实就是设计模式里面的装饰者模式。它通过组合的方式达到很高的灵活程度。
import React, { Component } from 'react'
export default (WrappedComponent, name) => {
class NewComponent extends Component {
constructor () {
super()
this.state = { data: null }
}
componentWillMount () {
let data = localStorage.getItem(name)
this.setState({ data })
}
render () {
return <WrappedComponent data={this.state.data} />
}
}
return NewComponent
}
这是react中一个鲜为人知的概念,它的使用门槛被开发团队故意加高,那是因为它是很危险的操作。
正如第二幅图所示,将父组件的某个状态放在一个地方,子组件无论层级有多深,都可以到这个地方去访问它。一如我们将整个React应用形象的比喻成一棵树,那么context其实就像是组件树上某棵子树的全局变量
class Index extends Component {
static childContextTypes = {
themeColor: PropTypes.string
}
constructor () {
super()
this.state = { themeColor: 'red' }
}
getChildContext () {
return { themeColor: this.state.themeColor }
}
render () {
return (
<div>
<Header />
<Main />
</div>
)
}
}
// getChildContext这个方法就是设置 context 的过程,它返回的对象就是 context(也就是上图中处于中间的方块),所有的子组件都可以访问到这个对象。
// 配套的 childContextTypes 与 propsType 类似,只是它用于验证context对象,记得一开始说的“加高门槛”吗?如果你要给组件设置 context,那么 childContextTypes 是必写的。
class Title extends Component {
static contextTypes = {
themeColor: PropTypes.string
}
render () {
return (
<h1 style={{ color: this.context.themeColor }}>React.js </h1>
)
}
}
// 子组件要获取 context 里面的内容的话,就必须写 contextTypes 来声明和验证你需要获取的状态的类型,它也是必写的,如果你不写就无法获取 context 里面的状态。
某个组件只要往自己的 context 里面放了某些状态,这个组件之下的所有子组件都直接访问这个状态而不需要通过中间组件的传递。一个组件的 context 只有它的子组件能够访问,它的父组件是不能访问到的,你可以理解每个组件的 context 就是瀑布的源头,只能往下流不能往上飞。
到这里我们就能够梳理出较为清晰的思路了,我们需要高阶组件
帮助我们从context
取数据,我们也需要写Dumb
组件帮助我们提高组件的复用性。所以我们尽量多地写 Dumb 组件,然后用高阶组件把它们包装一层,高阶组件和 context 打交道,把里面数据取出来通过 props
传给 Dumb 组件。
除了给高阶组件传入Dumb组件以外,还需要告诉高级组件我们需要什么数据,高阶组件才能正确地去取数据。
根据是否需要高度的复用性,把组件划分为 Dumb 和 Smart 组件,约定俗成地把它们分别放到 components 和 containers 目录下。