Vue的高阶组件在官方文档中并未提及,这个是一个舶来品,是React生态才有的一个概念。

但不妨碍我们使用它。

实际上Vue组件就是一个对象。根据高阶函数的概念

在数学和计算机科学中,高阶函数是至少满足下列一个条件的函数:

  1. 接受一个或多个函数作为输入。
  2. 输出一个函数

高阶组件也就是返回一个组件(对象数据)。

我们知道在使用Vue过程中,书写模板的方式有三种:

  1. 使用render
  2. 使用template属性
  3. 使用使用template模板

上述三种方式同时存在时,render的优先级是最高的。这在源码上是Vue首先对render这个参数做个判断,一旦有就直接使用了。

高阶组件有什么用呢?之前遇到一个问题,怎么对某些组件进行全局有效性拦截?我给出的方案是用mixins混入的方案,实际还可以用高阶组件。

比如我有一个Base.vue组件,一旦这个组件使用需要打印一些内容。

// Base.vue组件<span @click="handleClick">props: {{test}}
    export default {
  name: 'Base',
  props: {
    test: Number
  },
  methods: {
    handleClick () {      this.$emit('Base-click',{
        msg:'子组件emit'
      })
    }
  }
}" _ue_custom_node_="true">

我们可以使用template构建一个高阶组件,然后包裹Base

//template版本export default function HOC (Base) {    return {
      template: '',
      components: {        base: Base
      },
      mounted () {
        console.log('我是HOC mounted log')
      }
    }
  }

但是这个方案要求使用的vue是完整版而不是运行时版本。

使用render构建的高阶组件

export default function Console (Base) {    return {
      mounted () {
        console.log('我是HOC mounted log')
      },
      props: Base.props, // 继承pros      render (h) {        const slots = Object.keys(this.$slots)
          .reduce((acc, cur) => acc.concat(this.$slots[cur]), [])          // 手动更正 context
          .map(vnode => {
            vnode.context = this._self //绑定到高阶组件上
            return vnode
          }) // 继承slots

        return h(Base, {
          on: this.$listeners,
          props: this.$props,
          attrs: this.$attrs
        }, slots)
      }
    }
}

使用高阶组件

<wrapBase @Base-click="click1" :test="100">default slot//Parent.vueimport Base from "./Base.vue";// 使用hoc替代minxinimport HOC from "./hoc"; // 这里可以是template版本也可以是render版本const wrapBase = HOC(Base);

export default {
  components: {
    Base,
    wrapBase,
  },
  methods: {
      click1(msg){
          console.log(msg, 'msg')
      }
  }  //...};" _ue_custom_node_="true">

以上案例高阶组件用来进行日志输出。当然也可以用来做权限校验。