转载来源 感谢分享

Mixins 引入了无形的依赖

  • 应尽量构建无状态组件,Mixin 则反其道而行之
  • Mixin 可能会相互依赖,相互耦合,不利于代码维护
  • 不同的 Mixin 中的方法可能会相互冲突

举个例子

Mixins 有个主要用途是组件从其它数据源订阅数据:

class CommentList extends React.Component {
this.state = {
// "DataSource" 就是全局的数据源
comments: DataSource.getComments()
} componentDidMount() {
// 添加事件处理函数订阅数据
DataSource.addChangeListener(this.handleChange);
} componentWillUnmount() {
// 清除事件处理函数
DataSource.removeChangeListener(this.handleChange);
} handleChange = () => {
// 任何时候数据发生改变就更新组件
this.setState({
comments: DataSource.getComments()
})
} render() {
return (
<div>
{this.state.comments.map((comment) => (
<Comment comment={comment} key={comment.id} />
))}
</div>
)
}
}

当多个组件共用此逻辑时,使用 高阶组件 来优化:

const CommentListWithSubscription = withSubscription(
CommentList,
(DataSource) => DataSource.getComments()
) const BlogPostWithSubscription = withSubscription(
BlogPost,
(DataSource, props) => DataSource.getBlogPost(props.id)
) // 函数接受一个组件参数……
function withSubscription(WrappedComponent, selectData) {
// ……返回另一个新组件……
return class extends React.Component {
this.state = {
data: selectData(DataSource, props)
} componentDidMount() {
// ……注意订阅数据……
DataSource.addChangeListener(this.handleChange)
} componentWillUnmount() {
DataSource.removeChangeListener(this.handleChange)
} handleChange = () => {
this.setState({
data: selectData(DataSource, this.props)
})
} render() {
// ……使用最新的数据渲染组件
// 注意此处将已有的props属性传递给原组件
return <WrappedComponent data={this.state.data} {...this.props} />
}
}
}

高阶组件既不会修改 input 原组件,也不会使用继承复制 input 原组件的行为。相反,高阶组件是通过将原组件包裹(wrapping)在容器组件(container component)里面的方式来组合(composes)使用原组件。高阶组件就是一个没有副作用的纯函数。

抽取状态

说白了就是在无状态组件和其容器组件的关系中,通常让无状态组件不管理自己的状态,状态的管理交给外面的容器组件。

react-redux 的 connect 函数就用来抽取状态,它返回一个高阶组件。

假定你了解 Redux,那么可以看下 connect 的简易实现:

const doNothing = () => ({})

function connect(mapStateToProps=doNothing, mapDispatchToProps=doNothing) {
return function(WarppedComponent) {
class HOC extends React.Component {
this.state = {} componentDidMount() {
this.context.store.subscribe(this.onChange)
} componentWillUmount() {
this.context.store.unsubscribe(this.onChange)
} // HOC 保证 Redux 上 Store 状态变化的时候驱动这个组件的更新
onChange = () => this.setState({}) render() {
const store = this.centext.store
// 执行 getState 得到 Redux Store 状态
// 通过 dispatch 得到传递给 mapDispatchToProps 的 dispatch 方法
const newProps = {
...this.props,
...mapStateToProps(store.getState()),
...mapDispatchToProps(store.dispatch)
} return <WarppedComponent {...newProps} />
}
} // 创建新组件需要利用 Context 功能,所以定义了 types 属性,
// 从 Context 中获取名为 store 的值
HOC.contextTypes = { store.React.PropTypes.object } return HOC
}
}

浅析为什么用高阶组件代替 Mixins的更多相关文章

  1. Mixins 改成使用高阶组件调用

    把组件放在另外一个组件的 render 方法里面, 并且利用了 {...this.props} {...this.state} 这些  JSX 展开属性 对比下2种代码: 原始方式: <!DOC ...

  2. React 高阶组件浅析

    高阶组件的这种写法的诞生来自于社区的实践,目的是解决一些交叉问题(Cross-Cutting Concerns).而最早时候 React 官方给出的解决方案是使用 mixin .而 React 也在官 ...

  3. React文档(二十四)高阶组件

    高阶组件(HOC)是React里的高级技术为了应对重用组件的逻辑.HOCs本质上不是React API的一部分.它是从React的组合性质中显露出来的模式. 具体来说,一个高阶组件就是一个获取一个组件 ...

  4. React高阶组件总结

    在多个不同的组件中需要用到相同的功能,这个解决方法,通常有Mixin和高阶组件. Mixin方法例如: //给所有组件添加一个name属性 var defaultMixin = { getDefaul ...

  5. vue-mixins和vue高阶组件

    我们在开发过程中,因为需求的变更,往往会遇见对现有组件的改造和扩展. 那么我们有什么方法对现有组件进行改造和扩展呢? 常见的我们可以使用mixins方式 下面就让我们来看一下怎么使用mixins方式对 ...

  6. 聊聊React高阶组件(Higher-Order Components)

    使用 react已经有不短的时间了,最近看到关于 react高阶组件的一篇文章,看了之后顿时眼前一亮,对于我这种还在新手村晃荡.一切朝着打怪升级看齐的小喽啰来说,像这种难度不是太高同时门槛也不是那么低 ...

  7. React——高阶组件

    1.在React中higher-order component (HOC)是一种重用组件逻辑的高级技术.HOC不是React API中的一部分.HOC是一个函数,该函数接收一个组件并且返回一个新组件. ...

  8. react 高阶组件的 理解和应用

    高阶组件是什么东西 简单的理解是:一个包装了另一个基础组件的组件.(相对高阶组件来说,我习惯把被包装的组件称为基础组件) 注意:这里说的是包装,可以理解成包裹和组装: 具体的是高阶组件的两种形式吧: ...

  9. React 精要面试题讲解(五) 高阶组件真解

    说明与目录 在学习本章内容之前,最好是具备react中'插槽(children)'及'组合与继承' 这两点的知识积累. 详情请参照React 精要面试题讲解(四) 组合与继承不得不说的秘密. 哦不好意 ...

随机推荐

  1. IDEA/Git 提交/commit 忽略 文件夹

    commit的时候.idea文件夹被默认选中了,如果忘记点掉就会被提交上去,想要默认忽略其实很简单. 找到项目根目录处的.gitignore文件(如果是用git版本控制的话) 双击打开之后  我们在最 ...

  2. 微信小程序的生命周期和APP对象的使用

    1.生命周期和APP对象的使用: //app.js App({ onLaunch: function () { //调用API从本地缓存中获取数据 var logs = wx.getStorageSy ...

  3. database使用

    参照文档 https://www.cnblogs.com/laoqing/p/8542487.html

  4. WebLogic下Argument(s) "type" can't be null.

    启动项目出现Argument(s) "type" can't be null.异常.异常如下: java.lang.IllegalArgumentException: Argume ...

  5. 华为HCNA乱学Round 2:路由基础

  6. 第七周课程总结&实验报告

    课程总结 主要学习了抽象类与接口的应用 1.抽象类的成员可以具有访问级别 接口的成员全部public级别 2.抽象类可以包含字段 接口不可以 3.抽象类可以继承接口 接口不能继承抽象类 4.抽象类的成 ...

  7. http 中指定head中Content-Encoding属性为gzip 转换过程中的一些问题

    项目环境: 对接的服务放在微服务中 提供接口给应用层调用 ,微服务放需要 接受参数 并且转换成压缩格式给 第三方服务 本来以为需要自己压缩,httpclint 中已经封装好了GzipCompressi ...

  8. Spring(七)--Spring JDBC

    Spring JDBC 1.需要的实体类和数据库 2.需要的dao层 package com.xdf.dao; import com.xdf.bean.Student; import org.spri ...

  9. 干货 | 深入分析 string.intern() 方法

    首先我们来看一段代码: public class InternTest {      public static void main(String[] args) {     String str1 ...

  10. vue城市选择组件

    适用于vue的城市选择组件 仓库地址 基本功能: 支持全选.反选以及全部清空. 支持按拼音筛选. 勾选省份将会勾选省份下所有城市. 返回数据可灵活处理. 安装 npm install cn-regio ...