mixin

Mixin 设计模式

Mixin(混入)是一种通过扩大收集性能的形式,它实质上是将一个对象的属性拷贝到另一个对象下面去,能够拷贝多个属性到一个对象上,为了解决代码复用问题。

罕用的办法:JQuery 的 extend 办法。

var LogMixin = {  log: function() {    console.log('log');  },  componentDidMount: function() {    console.log('in');  },  componentWillUnmount: function() {    console.log('out');  }};var User = React.createClass({  mixins: [LogMixin],  render: function() {    return (<div>...</div>)  }});var Goods = React.createClass({  mixins: [LogMixin],  render: function() {    return (<div>...</div>)  }});

毛病

  1. Mixin 可能会相互依赖,互相耦合,不利于代码保护
  2. 不同的 Mixin 中的办法可能会互相抵触
  3. 当初大量应用 ES6 语法后,React.createClass 曾经勾销,这种形式也不再举荐

高阶组件(HOC)

高阶组件的定义:

高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 本身不是 React API 的一部分,它是一种基于 React 的组合个性而造成的设计模式。 (高阶组件是参数为组件,返回值为新组件的函数。)

具体的意思就是:
高阶组件能够看作 React 对装璜模式的一种实现,高阶组件就是一个函数,且该函数承受一个组件作为参数,并返回一个新的组件。他会返回一个加强的 React 组件。高阶组件能够让咱们的代码更具备复用性,逻辑性与抽象性,能够对 render 办法进行劫持,也能够管制 props 与 state。

const EnhancedComponent = higherOrderComponent(WrappedComponent);

实现高阶组件的两种形式:

  1. 属性代理: 高阶组件通过被包裹的 React 组件来操作 props
  2. 反向继承:高阶组件继承于被包裹的 React 组件。

属性代理

import React,{Component} from 'react';const HOC = (WrappedComponent) =>  class WrapperComponent extends Component {    state = { number: 0 };    btnClick = () => {        this.setState({            number: this.state.number++        })    }    render() {        const newProps = {            btnClick: this.btnClick,            number: this.state.number        }        return (            <div>                rere HOC                <WrappedComponent {...this.props} {...this.newProps} />            </div>        )    }}export default HOC;class MyComponent extends Component{    //...}export default HOC(MyComponent)

这里最重要的局部是render 办法中返回的 WrappedComponent 的 React 组件,这样就能够通过高阶组件来传递 props,这就是属性代理。

这样组件就能够一层层地作为参数被调用,原始组件就具备了高阶组件对它的润饰,也放弃了单个组件的封装性,与易用性。

特点

  1. 管制 props
    咱们能够在 HOC 外面对 props 进行增删查改等操作

    const MouseHoc = (MouseComponent, props) => {   props.text = props.text + "---I can operate props";   return class extends React.Component {       render() {           return (               <div style={{ height: "100%" }} onMouseMove={this.handleMouseMove}>                   <MouseComponent {...props} mouse={this.state} />               </div>           );       }   };};MouseHoc(Mouse, {   text: "some thing..."});
  2. 通过 refs 应用援用

    function refHOC(WrappedComponent) {    return class extends Component {        componentDidMount() {            this.wapperRef.log();        }        render() {            return (                <WrappedComponent                    {...this.props}                    ref={ref => {                        this.wapperRef = ref;                    }}                />            );        }    };}
  3. 形象 state
  4. 渲染劫持
    高阶组件能够在 render 函数中做十分多的操作,从而管制原组件的渲染输入。只有扭转了原组件的渲染,咱们都将它称之为一种渲染劫持。

    function visibleHOC(WrappedComponent) {   return class extends Component {       render() {           if (this.props.visible === false) return null;           return <WrappedComponent {...props} />;       }   };}

    参考 前端进阶面试题具体解答

  5. 应用其余元素包裹 WrappedCompoennt
    批改 props

反向继承

const MyContainer = (WrappedComponent) =>    class extends WrappedComponent{        render(){            return super.render();        }    }

这里返回的组件继承了 WrappedComponent,因为被动地继承了 WrappedComponent,所有的调用都会反向。

注意事项

  1. 当咱们利用 HOC 去加强另一个组件时,咱们理论应用的组件曾经不是原组件了,所以咱们拿不到原组件的任何动态属性,咱们能够在 HOC 的结尾手动拷贝他们

    function proxyHOC(WrappedComponent) {   class HOCComponent extends Component {       render() {       return <WrappedComponent {...this.props} />;       }   }   HOCComponent.staticMethod = WrappedComponent.staticMethod;   // ...   return HOCComponent;}
2. 不要在 render 办法内创立高阶组件3. 不要扭转原始组件(高阶组件就是一个没有副作用的纯函数。)4. 透传不相干的 props### 解决的问题1. 高阶组件就是一个没有副作用的纯函数,各个高阶组件不会相互依赖耦合2. 高阶组件也有可能造成抵触,但咱们能够在恪守约定的状况下防止这些行为3. 高阶组件并不关怀数据应用的形式和起因,而被包裹的组件也不关怀数据来自何处。高阶组件的减少不会为原组件减少累赘### 存在的问题1. HOC 须要在原组件上进行包裹或者嵌套,如果大量应用 HOC,将会产生十分多的嵌套,这让调试变得十分艰难2. HOC 能够劫持 props,存在雷同名称的 props,则存在笼罩问题在不恪守约定的状况下也可能造成抵触,而且 react 并不会报错。3. 当存在多个 HOC 时,你不晓得 Props 是从哪里来的。4. HOC 属于动态构建,动态构建即是从新生成一个组件,即返回的新组件,不会马上渲染,即新组件中定义的生命周期函数只有新组件被渲染时才会执行。**在这个范式下,代码通过一个相似于 装璜器(decorator) 的技术进行共享。首先,你的一个组件定义了大量须要被渲染的标记,之后用若干具备你想用共享的行为的组件包裹它。因而,你当初是在 装璜 你的组件,而不是混入你须要的行为!## Render props> Render Props 从名知义,也是一种剥离重复使用的逻辑代码,晋升组件复用性的解决方案。在被复用的组件中,**通过一个名为“render”(属性名也能够不是 render,只有值是一个函数即可)的属性,该属性是一个函数,这个函数承受一个对象并返回一个子组件,会将这个函数参数中的对象作为 props 传入给新生成的组件**。### 它的特点1. 传入函数的属性,就是  想要共享的 state,这个雷同的 state 是组件的状态,或者行为2. 术语 “render prop” 是指一种技术,用于应用一个值为函数的 prop 在 React 组件之间的代码共享。3. render prop 仅仅就是一个函数。4. `render prop`是一种模式,重点是 prop,而不是 render,任何被用于告知组件须要渲染什么内容的函数 prop 在技术上都能够被称为 “render prop”.5. 这里的组合模型是 动静的!每次组合都产生在 render 外部,因而,咱们就能利用到 React 生命周期以及天然流动的 props 和 state 带来的劣势。6. 具备 render prop 的组件承受一个函数,该函数返回一个 React 元素并调用它,而不是实现本人的渲染逻辑### 小栗子

<DataProvider render={data => (
<h1>Hello {data.target}</h1>
)}/>

#### 劣势1. 不必放心 Props 是从哪里来的, 它只能从父组件传递过去。2. 不必放心 props 的命名问题。3. render props 是动静构建的。能够用 `render props`来代替 HOC

const withMouse = (Component) => {
return class extends React.Component {

render() {  return <Mouse render={mouse => (    <Component {...this.props} mouse={mouse}/>  )}/>}

}
}

## Hook在 Hooks 呈现以前,咱们总是纠结的问题:1. 无状态组件 VS Class 组件2. 生命周期   componentDidMount 和 componentDidUpdate 须要做雷同的事件3. this 指向   为了保障 this 的指向正确,咱们常常这么写   

this.handleClick = this.handleClick.bind(this)
<button onClick={() => this.handleClick(e)}>

4. HOC 和 render props 减少咱们代码的层级关系动机Hook 的作用1. 咱们的函数变成了一个有状态的函数2. Hooks 实质上就是一类非凡的函数,它们能够为你的函数型组件(function component)注入一些非凡的性能(生命周期钩子的性能:useEffect;上下文(context):useContext)3. 解决 this 指向问题### State Hooks### Effect Hooks咱们写的有状态组件,通常会产生很多的副作用(side effect)。之前都把这些副作用的函数写在生命周期函数钩子里,比方 componentDidMount,componentDidUpdate 和 componentWillUnmount。而当初的 useEffect 就相当与这些申明周期函数钩子的集合体。它以一抵三。用 Effect Hooks 来解决这个这些副作用。#### 留神点1. react 首次渲染和之后的每次渲染都会调用一遍传给 useEffect 的函数。而之前咱们要用两个申明周期函数来别离示意首次渲染(componentDidMount),和之后的更新导致的从新渲染(componentDidUpdate)。2. 函数是异步执行的,而之前的 componentDidMount 或 componentDidUpdate 中的代码则是同步执行的3. 怎么解绑副作用4. 跳过一些不必要的副作用函数### 应用范畴只能在 React **函数式组件或自定义** Hook 中应用 Hook。Hook 的提出次要就是为了解决 class 组件的一系列问题,所以咱们不能在 class 组件中应用它。相比函数,编写一个 class 可能须要把握更多的常识,须要留神的点也越多,比方 this 指向、绑定事件等等。另外,**计算机了解一个函数比了解一个 class 更快。Hooks 让你能够在 classes 之外应用更多 React 的新个性。**