前阵子做厂里的需求,允许用户编辑算法生成的 CSS,以便将我厂的产品应用到生产环境。我们允许用户使用可视化编辑器编辑某条特定规则,大约如下图所示:
我们知道,CSS 规则有优先级,优先级高的规则会覆盖优先级低的规则中的同名属性;也会继承低优先级规则里没有被覆盖的属性。反应到我们的可视化编辑器里,就是:
- 有些属性用户不能删除,因为那是从低优先级的样式里继承来的
- 有些属性用户修改了也不会生效,因为会有更高优先级的规则把它覆盖掉
所以我们希望给用户一些提示,避免他们实际操作的时候感到疑惑。那么问题来了:怎么实现呢?
从图上可以看出,CSS 可视化编辑器挺复杂的,有些属性可以直接编辑,比如 visibility
,独立生效,那随便写个 <input type="checkbox">
就行;有些则与其它属性一起发生作用,比如 align-items
,那我们就需要比较复杂的组件,里面会嵌套别的组件。
所以一般的 v-bind
方式就不适用:我计算出优先级之后,需要传递多次才能穿透组件间的嵌套关系,太复杂,很难用。我们需要更简单的传递方案。好在 Vue 提供了 provide
/inject
方式。
Vue 官方称这个功能为“依赖注入”,我们在父组件上使用 provide
暴露一些属性,然后在子组件里用 inject
把这些属性拿进来使用。不管子组件和父组件之间嵌套了几层,都可以获取到:
provide() {
return {
foo: this.foo
}
}
inject: ['foo']
用法比较简单,就这么两步,但是有一些注意事项:
- 注入的变量默认没有响应式,Vue 就是这么设计的,这样可以避免一些问题。如果需要响应式,那就需要传入包含响应式的变量,比如
data
或者computed
。 - 如果你用 vue-property-decorator,那么需要用
ProvideReactive
和InjectReactive
。 - 这个依赖注入和设计模式里的 DI 不是一回事,面试时不要乱讲。
- 不要滥用这个设计,只有不特定层级子组件需要用到属性,才这么做。
扩展阅读:
欢迎吐槽,共同进步