Zonebit

个人的奋斗还是历史的进程?

View the Project on GitHub

25 July 2018

vue中的依赖注入

by ganlyun

最近在写anchor组件的时候出现了一个问题,例子的template如下

<Anchor>
    <Link href="#components-anchor-demo-basic" title="Basic demo" />
    <Link href="#components-anchor-demo-fixed" title="Fixed demo" />
    <Link href="#API" title="API">
      <Link href="#Anchor-Props" title="Anchor Props" />
      <Link href="#Link-Props" title="Link Props" />
    </Link>
</Anchor>

在API Link嵌套了两个Link,因为每个Link被点击后都需要在Anchor组件上触发自定义事件以处理样式效果以及页面滑动定位的操作,而Link又要满足嵌套Link的需要,我首先想到的是从Link组件中使用$parent链式引用父组件,但是这显然是一个令人困惑的实现,而且会因为不确定Link处在第几层嵌套而增加额外的逻辑,官方文档中是这么描述的:

使用 $parent 属性无法很好的扩展到更深层级的嵌套组件上。 这也是依赖注入的用武之地,它用到了两个新的实例选项:provideinject

具体操作如下

在Anchor组件的选项对象中加入

provide () {
    return {
        anchorRoot: this
    }
}

在Link组件的选项对象中加入

inject: ['anchorRoot']

这样我们就通过anchorRoot指向了Anchor组件,在Link中可以直接使用 this.anchorRoot 完成引用

实际上,你可以把依赖注入看作一部分“大范围有效的 prop”,除了:

  • 祖先组件不需要知道哪些后代组件使用它提供的属性
  • 后代组件不需要知道被注入的属性来自哪里

最后引用文档中对依赖注入缺点的描述:

然而,依赖注入还是有负面影响的。它将你的应用以目前的组件组织方式耦合了起来,使重构变得更加困难。同时所提供的属性是非响应式的。这是出于设计的考虑,因为使用它们来创建一个中心化规模化的数据跟使用 $root做这件事都是不够好的。如果你想要共享的这个属性是你的应用特有的,而不是通用化的,或者如果你想在祖先组件中更新所提供的数据,那么这意味着你可能需要换用一个像 Vuex 这样真正的状态管理方案了。

tags: vue - 依赖注入 - dependency injection - antue