转载来源 感谢分享

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. Netflix颠覆HR:我们只雇“成年人”

    员工的最佳福利,是与优秀者一起工作 ● Patty McCord / 文 李钊/译 担任Netflix的首席人才官时,我与CEO里德·黑斯廷斯一起做了一份127页的PPT,命名为<自由& ...

  2. Windows系统Git Bash Sock5代理

    git config --global https.proxy http://127.0.0.1:1080 git config --global https.proxy https://127.0. ...

  3. oracle 在sql中显示blob的字符串

    最近在用oracle的过程中用到了对blob字段模糊查询的问题,对oracle来说,我并不是高手,找了很多的资料终于能够查出来了. blob字段直接用 select * from table_name ...

  4. CTF—攻防练习之HTTP—PUT上传漏洞

    主机:192.168.32.152 靶机:192.168.32.159 中间件PUT漏洞 包括apache,tomcat,IIS等中间件设置支持的HTTP方法(get,post,head,delete ...

  5. java课堂疑问解答与思考2

    问题一 编写一个方法,使用以上算法生成指定数目(比如1000个)的随机整数. 答:Xn+1=(7^5*Xn)mod(2^31-1) 程序源码: import java.util.Random; imp ...

  6. 【VS开发】【图像处理】GigE和USB3 vision选择?

    [VS开发][图像处理]GigE和USB3 vision选择? 具体得看你现场的应用吧,如 现场需要的工作距离,网线可达到100m以内,USB3.0一般般的5m以内: GigE双端都有卡扣,保证了与相 ...

  7. mongodb 数据库操作 -- 》常用命令

    首先需要下载数据库,安装后,找到bin目录,点开bin目录,复制当前路径配置到环境变量中 和bin的同级下,需要建立一个data/db文件夹,该文件夹并不会自动生成,必须手动设置   启动数据库  看 ...

  8. c语言l博客作业11

    问题 答案 这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-2/homework/8655 我在 ...

  9. Python常用方法库备忘(一)_当前路径下文件夹和文件

    #!/usr/bin/env python # -*- coding:utf-8 -*- # --------------*-------------- # @Author : AilF # @Tim ...

  10. Linux环境下Oracle安装参数设置

    前面讲了虚拟机的设置和OracleLinux的安装,接下来我们来说下Oracle安装前的准备工作.1.系统信息查看系统信息查看首先服务器ip:192.168.8.120服务器系统:Oracle Lin ...