Vue 依赖注入 (provide/inject)

在看 Element 面包屑组件的源码时记录

缘起

首先看一段 Breadcrumb.vue 的实现代码。

<template>
  <div class="el-breadcrumb" aria-label="Breadcrumb" role="navigation">
    <slot></slot>
  </div>
</template>
<script>
  export default {
    name: 'ElBreadcrumb',
    props: {
      separator: {
        type: String,
        default: '/'
      },
      separatorClass: {
        type: String,
        default: ''
      }
    },
    provide() {
      return {
        elBreadcrumb: this
      };
    },
    mounted() {
      const items = this.$el.querySelectorAll('.el-breadcrumb__item');
      if (items.length) {
        items[items.length - 1].setAttribute('aria-current', 'page');
      }
    }
  };
</script>

这里,Breadcrumb 直接把自己的 this 暴露给下级组件,然后注入到 BreadcrumbItem 组件中,以达到向子孙组件传递信息的目的,下面就来总结一下 Vueprovide/inject 的用法。

参数详解

  • provideObject | () => Object
  • injectArray| { [key: string]: string | Symbol | Object }

详细介绍

  1. Vue 2.2.0 新增,主要为高阶插件/组件库跨级访问祖先组件数据的方法,并不推荐直接用于应用程序代码中。

  2. provideinject 绑定并不是可响应的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。

  3. Symbol 作为 key

const s = Symbol()

const Provider = {
  provide () {
    return {
      [s]: 'foo'
    }
  }
}

const Child = {
  inject: { s },
  // ...
}
  1. inject 作为 propsdata 默认值,只在 ^2.2.1 有效,以下版本注入值会在初始化之后得到。
const Child = {
  inject: ['foo'],
  data () {
    return {
      bar: this.foo
    }
  }
}
  1. 参数化配置,只在 ^2.5.0 有效
// 设置默认值
const Child = {
  inject: {
    foo: { default: 'foo' }
  }
}

// 工厂方法设置默认值
const Child = {
  inject: {
    foo: {
      from: 'bar',
      default: () => [1, 2, 3]
    }
  }
}

// 从不同名字的属性注入
const Child = {
  inject: {
    foo: {
      from: 'bar',
      default: 'foo'
    }
  }
}

Reference

  1. Vue.js 中文文档
  2. Element 源码