快速开始

写在前头

Vdi 依赖于redi,它是一个基于 vue3 的依赖注入插件,它可以让你在 vue3 中使用 redi 的 api,并且可以增强你的 vue3 开发,写出更少耦合、更易调整、更易维护的代码

  • Vdi 只能在 vue3 中使用
  • 如果不了解依赖注入模式可能会对这个插件有一定的困惑,可以先去阅读 redi 的博客
  • 为什么不是injection-js,因为 injection-js 依赖于 ts 元数据,需要安装reflect-metadata,而且继承的父类中的依赖不会被查找出来,需要在 class 中手动注入
  • 文档因为我的个人能力有些很可能云里雾里,不如直接使用启动模板看看

安装

选择你常用的包管理器,因为依赖于redi所以要跟vdi一并安装

$ npm install @wendellhu/redi vdi

配置

在使用redi时我们可能需要用到装饰器和类,所以配置tsconfig.json

{
    "compilerOptions": {
        "experimentalDecorators": true,
        "useDefineForClassFields": false
    }
}

如何使用

vdi 并不需要整个项目使用依赖注入,只需要:

单独页面使用

首先创建一个服务:

// count.service.ts
import { ref } from 'vue'
export class CountService {
    count = ref<number>(0)
    inc() {
        this.count.value++
    }
}

提示

  • 如果需要在服务中使用其他依赖,在constructor中使用装饰器@inject获取依赖

  • 在服务中可以使用ref创建响应式数据,如果服务是从上层注入的,我们的这个服务就变成一个简单的状态管理了

    例子
    import { inject } from '@wendellhu/redi'
    // 引入其他服务
    import { OtherService } from './other.service'
    // count.service.ts
    import { ref } from 'vue'
    export class CountService {
        constructor(@Inject(OtherService) public OtherService: OtherService) {}
        count = ref<number>(0)
        inc() {
            this.count.value++
        }
    }
    

随后在页面上使用onProvider注入刚刚创建的服务,并使用useDependency self 为 true 引用当前组件注入的服务







 


 







<script setup lang="ts">
import { onProvider, useDependency } from 'vdi'

import { CountService } from './count.service'

//在当前组件注入依赖
onProvider([[CountService]])

//获取提供的依赖,self为true时候获取的是当前组件的依赖
const countService = useDependency(CountService, { self: true })
</script>

<template>
    {{ countService.count }}
    <button @click="countService.inc">修改</button>
</template>

层级的依赖注入

在上面的例子中我们为单独页面使用了依赖注入,而这个例子我们从父组件注入依赖,子组件获取依赖来传递状态

首先在父组件onProvider注入刚刚的服务








 


 







<!--Father.vue -->
<script setup lang="ts">
import { onProvider, useDependency } from 'vdi'

import { CountService } from './count.service'

//在父组件组件注入依赖
onProvider([[CountService]])

//因为是从该组件注入,所以需要self来获取自身依赖
const countService = useDependency(CountService, { self: true })
</script>

<template>
    父组件: {{ countService.count }}
    <button @click="countService.inc">count+</button>
</template>

在子组件中使用useDependency获取依赖,注意此时不要使用 self 为 true,因为要获取上层的依赖,而不是当前组件的依赖








 









<!--Child.vue -->
<script setup lang="ts">
import { onProvider, useDependency } from 'vdi'

import { CountService } from './count.service'

//获取提供的依赖,不需要使用self,因为父组件已经注入了依赖
const countService = useDependency(CountService)
</script>

<template>
    <div class="child">
        子组件: {{ countService.count }}
        <button @click="countService.inc">count+</button>
    </div>
</template>

须知

  • 在组件使用onProvider注入依赖之后,该组件之下的每一层都能获取顶层的依赖,直到同一个依赖在下层被再次注入,则从下层开始获取到的是再次注入的依赖

  • 在需要获取从上层提供的依赖时,useDependency会自动寻找上层注入器获取依赖,不要使用 self,因为self代表获取当前组件自身依赖

全局注入

import { vdi } from 'vdi'
import { createApp } from 'vue'
import AppVue from './App.vue'

createApp(AppVue)
    .use(vdi([[TestService]]))
    .mount('#app')

更多依赖注入的 api

vdi 本身是基于redi,所以在类中的使用方式和 redi 一样,只是不需要创建 Injector, 更多 api 查看redi文档