Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

读《探索Vue高阶组件》 #11

Open
AnnVoV opened this issue May 20, 2018 · 0 comments
Open

读《探索Vue高阶组件》 #11

AnnVoV opened this issue May 20, 2018 · 0 comments

Comments

@AnnVoV
Copy link
Owner

AnnVoV commented May 20, 2018

HOC 组件的特点

  • 1.高阶组件应该是无副作用的纯函数,且不应该修改原组件
  • 2.高阶组件不关心你传递的数据(props)是什么,并且被包装组件(WrappedComponent)不关心数据来源
  • 高阶组件收到的props应该透传给被包装组件(WrappedComponent)

React 中的高阶函数(High Order Component)

比如我们要把一个ajax获取数据的功能放到一个高阶组件里

// APILoader.js
// 首先高阶函数的意思就是通过一个函数,传入一个函数,得到另一个函数So
import api from 'component/api'
import React from 'react'

function AjaxLoader() {
  // 首先这里要返回个函数
  return function(MyComponent) {
    class APILoader extends React.Component {
      constructor(props) {
        super(props)
        this.state = {
          ajaxData: {}
        }
      }
      componentDidMount() {
        // 异步加载数据
        api.then((data)=> {
          this.setState({
            ajaxData: data
          })
        })
      }
      render() {
        return (
          <MyComponent data={this.state.ajaxData}/>
        )
      }
    }
    return APILoader
  }
}
export default AjaxLoader;
// BookLoader.js
import APILoader from './APILoader'
import React from 'react'
class Book extends React.Component {
  constructor(props) {
    super(props)
  }
  render() {
    const {name, author} = this.props;
    return (
      <section>
        <div>{name}</div>
        <div>{author}</div>
      </section>
    )
  }
}
export default APILoader()(Book)

mixin 与 HOC 对比

![IMAGE](quiver-image-url/1B82D7CF4D0F1E8308C7CB963525AC1F.jpg =652x309)

在mixin中,组件和mixin之间是相互感知的。基于在多个mixin同时作用于一个组件上时,mixin之间也可能相互影响。这个就像复杂的多角恋关系。

在HOC中,组件对包裹自己的HOC毫不知情,只知道接受自己想要的props,可以单纯地作自己组件份内的事情。要给组件附加的特定逻辑(包括props、methods、computed等),都在HOC中实现和管理。HOC更像是一个暗恋者,默默地为组件做了一些事情,组件却不知道(也没必要知道)。

Vue中如何实现HOC

ps: 关于slot 的部分如何解决,我还没有搞明白。。。
vue 中一般我们都用Mixin,那在Vue中如何实现HOC组件呢?(vue中hoc的实现依赖于render函数,先回顾下render函数)

render函数中的Vnode数据对象

  {
    // v-bind: class
    'class': {
      foo: true,
      bar: false
    },
    // v-bind: style
    style: {
      color: 'red',
      fontSize: '14px'
    },
    // 正常的HTML特性
    attrs: {
      id: 'foo'
    },
    // 组件props
    props: {
      myProp: 'bar'
    },
    // DOM属性
    domProps: {
      innerHTML: 'baz'
    },
    // 事件监听基于on
    on: {
      click: this.clickHandler
    }
    // 自定义指令
    directives: [
      {
        name: 'my-custom-directive',
        value: '2',
        expression: '1 + 1',
        arg: 'foo',
        modifiers: {
          bar: true
        }
      }
    ]
    // 作用域插槽
    // { name: props => VNode | Array<VNode> }
    scopedSlots: {
      default:props => createElement('span', props.text)
    },
    // 如果组件是其他组件的子组件,需为插槽指定名称
    slot: 'name-of-slot',
    // 其他特殊顶层属性
    key: 'myKey',
    ref: 'myRef'
  }

hoc组件

import Ajax from 'api/ajax';
const hoc = (component) => {
  // component 上的props
  const inheritedProps = component.props || [];
  return {
    render(createElement) {
      return createElement(component, {
        props: {
          ...inheritedProps,
          data: this.fetchedData
        }
      })
    },
    // hoc 的props和component保持一致
    props: [...inheritedProps],
    data() {
      return {
        fetchedData: {}
      }
    },
    mounted() {
      Ajax.get('/user/getUserInfo')
        .then((data) => {
          this.fetchedData = data;
        });
    }
  }
}
export default hoc;

baseComponent组件

<template>
    <div>
        <span>name:{{data}}</span>
        <button>click</button>
    </div>
</template>

<script>
    export default {
        props: ['url', 'data'],
        mounted() {
            console.log('来自baseComp的mounted');
        }
    }
</script>

app.js

import hoc from './hoc';
import BaseComp from './baseComp'

export default {
  ...
  components: {
    'enhance-comp': hoc(BaseComp)
  }
}

深入阅读资料:

http://hcysun.me/2018/01/05/%E6%8E%A2%E7%B4%A2Vue%E9%AB%98%E9%98%B6%E7%BB%84%E4%BB%B6/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant