Vue 使用 Provide/Inject 向子组件内注入数据

前阵子做厂里的需求,允许用户编辑算法生成的 CSS,以便将我厂的产品应用到生产环境。我们允许用户使用可视化编辑器编辑某条特定规则,大约如下图所示:

我们知道,CSS 规则有优先级,优先级高的规则会覆盖优先级低的规则中的同名属性;也会继承低优先级规则里没有被覆盖的属性。反应到我们的可视化编辑器里,就是:

  1. 有些属性用户不能删除,因为那是从低优先级的样式里继承来的
  2. 有些属性用户修改了也不会生效,因为会有更高优先级的规则把它覆盖掉

所以我们希望给用户一些提示,避免他们实际操作的时候感到疑惑。那么问题来了:怎么实现呢?

从图上可以看出,CSS 可视化编辑器挺复杂的,有些属性可以直接编辑,比如 visibility,独立生效,那随便写个 <input type="checkbox"> 就行;有些则与其它属性一起发生作用,比如 align-items,那我们就需要比较复杂的组件,里面会嵌套别的组件。

所以一般的 v-bind 方式就不适用:我计算出优先级之后,需要传递多次才能穿透组件间的嵌套关系,太复杂,很难用。我们需要更简单的传递方案。好在 Vue 提供了 provide/inject 方式。

Vue 官方称这个功能为“依赖注入”,我们在父组件上使用 provide 暴露一些属性,然后在子组件里用 inject 把这些属性拿进来使用。不管子组件和父组件之间嵌套了几层,都可以获取到:

provide() {
  return {
    foo: this.foo
  }
}
inject: ['foo']

用法比较简单,就这么两步,但是有一些注意事项:

  1. 注入的变量默认没有响应式,Vue 就是这么设计的,这样可以避免一些问题。如果需要响应式,那就需要传入包含响应式的变量,比如 data 或者 computed
  2. 如果你用 vue-property-decorator,那么需要用 ProvideReactiveInjectReactive
  3. 这个依赖注入和设计模式里的 DI 不是一回事,面试时不要乱讲。
  4. 不要滥用这个设计,只有不特定层级子组件需要用到属性,才这么做。

扩展阅读:

如果您觉得文章内容对您有用,不妨支持我创作更多有价值的分享:


已发布

分类

来自

评论

欢迎吐槽,共同进步

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据