高阶组件的特点和高阶函数类似,高阶函数接受一个/多个函数作为参数,返回另一个函数,高阶组件则是组件作为参数,返回另外一个组件。只要满足其中2个条件之一即可。

高阶组件在一些场景下可以对组件进行复用,增强组件功能,控制渲染的内容。

在 Vue 里创建高阶组件:

场景1 页面鉴权

// pageA.vue
<script>
export default {
  name: 'PageA',
  template: '<div>pageA</div>'
}
</script>

// login.vue
<script>
export default {
  name: 'Login',
  template: '<div>login</div>'
}
</script>  

// auth.js
import PageLogin from './page/login'

function getToken() {
  return 'token'
}

function auth(component) {
  return {
    props: component.props,
    render(h) {
      if (getToken()) {
        const slots = Object.keys(this.$slots).reduce(
          (arr, key) => arr.concat(this.$slots[key]),
          []
        )
        return h(
          component,
          {
            props: this.$props,
            attrs: this.$attrs,
            on: this.$listeners
          },
          slots
        )
      } else {
        return h(PageLogin)
      }
    }
  }
}  

// 使用  
import auth from './auth'
import pageA from './page/pageA.vue
// 需要验证的时候调用auth函数就能实现页面鉴权,pageA页面无需修改任何东西
const AuthPageA = auth(PageA) 

export default {
  components: {
    AuthPageA
  }
}

场景2 复用组件

// list.vue 
import getProducts from '../api'

export default {
  props: {
    type: String
  },
  data () {
    return {
      products: []
    }
  },
  template: '<div>list</div>',
  mounted () {
    getProducts(this.type).then(products => {
      this.products = products
    })
  }
}

// createList.js  
import List from './list'
export default function createList (type) {
  return {
    render (h) {
      return h(List, { props: { type } })
    }
  }
}

// 使用: 
// 创建一个销售列表  
export default createList('sales')  
// 创建一个互换商品列表  
export default createList('swap')

总结

Vue 里使用 HOC 没有 React 里用得那么灵活,React 大部分时候是写函数,和高阶组件的契合度高。Vue 里如果不用高阶组件,也可以用 mixins 、组件嵌套的方式来解决这些问题,具体方式根据实际业务场景选择。