Component
1. 纯组件(prueComponent)
React.PureComponent和React.Component类似,都是定义一个组件类,不同的是React.PureComponent实现了shouldComponentUpdate()
2. 函数组件
定义React最简单的方法就是定义一个函数组件,它接受单一的props并返回一个React元素
- 函数组件也称为无状态组件:函数组件的输入输出都由props决定,不会产生任何副作用
- 函数组件也是展示组件:函数组件无法修改props、无法使用state以及组件的生命周期
- 函数组件是一个纯组件:函数组件的功能只是接收props,渲染页面,它不执行与UI无关的逻辑处理
- 函数组件优于类组件:函数组件相对于类组件,更加简洁,无论是复用性还是性能
3. 受控组件 && 非受控组件
受控组件和非受控组件主要取决于组件是否受父级传入的props控制 受控组件:受父级传入的props控制
与 html 不同的是,在 React中,
<input>或<select>、<textarea>等这类组件,不会主动维持自身状态,并根据用户输入进行更新。它们都要绑定一个onChange事件;每当状态发生变化时,都要写入组件的 state 中,在 React 中被称为受控组件。 注意:<input type="file" />,它是一个非受控组件。
非受控组件:不受父级传入的props控制,数据只保存在组件内部的state上(因为外部没有办法控组state)
4. 有状态组件 && 无状态组件
- 有状态组件 - 通过state管理状态
- 无状态组件 - 输入输出完全由props决定,且不产生任何副作用
无状态组件一般搭配高阶组件(HOC)一起使用,高阶组件用来托管state,Redux就是通过store管理数据源和所有状态,其中所以负责展示的组件都使用无状态函数式的写法
5. 展示组件 && 容器组件
-
展示组件:展示组件指不关心数据是怎么加载和变动的,只关注于页面展示效果的组件。
- 只能通过 props 的方式接收数据和进行回调(callback)操作
- 很少拥有自己的状态,即使有也是用于展示UI状态的
- 通常允许通过 this.props.children 方式来包含其他组件
- 内部可以包含展示组件和容器组件,通常会包含一些自己的DOM标记和样式(style)
- 对应用程序的其他部分没有依赖关系,例如Flux操作或store。
- 会被写成函数式组件除非该组件需要自己的状态,生命周期或者做一些性能优化。
-
容器组件:容器组件只关心数据是怎么加载和变动的,而不关注于页面展示效果。
- 内部可以包含容器组件和展示组件,但通常没有任何自己的DOM标记,除了一些包装divs,并且从不具有任何样式。
- 提供数据和行为给其他的展示组件或容器组件。
- 可以调用 Flux 操作并将它们作为回调函数(callback)提供给展示组件。
- 往往是有状态的,因为它们倾向于作为数据源
- 通常使用高阶组件生成,例如React Redux的connect()
6. 高阶组件
- 高阶函数定义:接收函数作为输入,或者输出另一个函数的一类函数
- 高阶组件定义:接收React组件作为输入,输出一个新的React组件的组件。 更通俗的说,高阶组件通过包裹(wrapped)被传入的Rract组件,经过一系列处理,最终返回一个相对增强的(enhanced)的React组件,供其他组件调用,使我们的代码更具有复用性、逻辑性、抽象特性。它可以对render方法做劫持,也可也控制props、state
- 实现高阶组件的方法有以下两种:
- 属性代理(props proxy):高阶组件通过被包裹的 React 组件来操作 props。
- 反向继承(inheritance inversion):高阶组件继承于被包裹的 React 组件。
// 属性代理 export default function withHeader(WrappedComponent) { return class HOC extends React.Component { // 继承与 React.component render() { const newProps = { test:'hoc' } // 透传props,并且传递新的newProps return <div> <WrappedComponent {...this.props} {...newProps}/> </div> } } } // 反向继承 export default function (WrappedComponent) { return class Inheritance extends WrappedComponent { // 继承于被包裹的 React 组件 componentDidMount() { // 可以方便地得到state,做一些更深入的修改。 console.log(this.state); } render() { return super.render(); } } } - 注意:
- 不要在 HOC 内修改一个组件的原型(或以其它方式修改组件)
- 不要在 render() 方法中创建 HOC,否则,每一次渲染,都会重新创建渲染 HOC
- 必须将原始组件的静态方法在 HOC 中做拷贝,否则 HOC 将没有原始组件的任何静态方法
- Refs 属性不能贯穿传递,我们可以使用 React.forwardRef 解决