# inject-provide **Repository Path**: shawroger/inject-provide ## Basic Information - **Project Name**: inject-provide - **Description**: nodejs简单注入库 - **Primary Language**: TypeScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-03-30 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Inject-Provide `inject-provide` 是一个极简洁的 **nodejs** 注入框架,运行过程中需要装饰器的支持,建议使用 **TypeScript** 作为运行环境。 # 安装 ```bash npm install inject-provide --save ``` # 基本使用 `inject-provide` 的使用方法非常简单,只有 7 个 API。 - 注入: Inject, AutoInjected - 提供:Provide, Offer - 注册:createStore - 默认库:rootStore - 注入库工具类:storeController - 事件处理:createEvent ## 创建注入库 ```ts import { createStore } from "inject-provide"; export newStore = createStore("newStore"); ``` 这一步创建过程是可选的,`inject-provide` 已经构建了一个默认的根注入库,即 `rootStore`,在所有不指明的注入 store 都会默认注入到 `rootStore`中。 ## 提供类 ```ts import { Provide, rootStore } from "inject-provide"; import { newStore } from "./my-store"; @Provide({ name: symbol("ProvideCar") store: [newStore, rootStore], args: ["BMW"] }) class ProvideCar { constructor(public name: string) {} getName() { return this.name; } } ``` 其中,`Provide` 的 name 参数是可选的,为空的时候会将类的 toString() 形式作为注入的令牌注入到 `rootStore` 中。 `Provide` 的 store 参数是可选的,为空的时候会注入到 `rootStore` 中,支持传入数组和单个 Store,但是在数组中如果仍希望注入到 `rootStore` 则需要手动加入。 `Provide` 的 args 参数也是可选的,args 即为构造函数中未被注入的参数,按顺序暴露在 args 参数数组中,在提交到注入库的时候会被初始化。 ## 使用注入服务 ```ts import { Inject } from "inject-provide"; import { ProvideCar } from "./provide-car"; import { newStore } from "./my-store"; class UseCar { constructor(@Inject(ProvideCar, newStore) public car: ProvideCar) {} getCarName() { return this.car.getName(); } } ``` 其中,`Inject` 的第一个参数是令牌,建议使用类名作为令牌,为空的时候会注入到 `rootStore` 中。 第二个参数为目标的注入库,`inject-provide` 会在在该库中查找待注入的数据,默认为 `rootStore`。 ## 使用自动注入 ```ts import { AutoInject } from "inject-provide"; import { UseCar } from "./use-car"; const result = AutoInject(UseCar); result.getCarName(); //BMW ``` # 进阶技巧 ## 参数注入 在构造函数中,如果有多个需要注入和不注入的参数,要把需要注入的参数放在前面 ```ts import { Inject } from "inject-provide"; import { ProvideCar } from "./provide-car"; class UseCar { constructor( @Inject(ProvideCar) public car: ProvideCar, public ownerAge: number, public ownerName: string // 不需要Inject的放在后面 ) {} getCarName() { return this.car.getName(); } } ``` ## 非注入的处理 自动注入时,不在注入服务中的参数按顺序写在后面 ```ts import { AutoInject } from "inject-provide"; import { UseCar } from "./use-car"; const result = AutoInject(UseCar, 25, "Alice"); result.getCarName(); //BMW result.ownerAge === 25; // true ``` ## 主动注入 Offer 通过 `Offer`, 可以使用直接提供服务的方式,为其他类型提供注入功能 ```ts import { Offer } from "inject-provide"; import { newStore } from "./my-store"; const obj = { name: "Bob", age: 20 }; Offer(obj, { store: newStore }); // 直接注入obj对象的地址 ``` 默认情况下,Offer 会使用 new 方法来初始化一个函数类型 (ES5 类),如果你希望注入一个纯粹的函数,那么请使用 pure 参数,来表明这是一个简单的函数 ```ts import { Offer } from "inject-provide"; import { newStore } from "./my-store"; const add = (num: number) => num + 1; Offer(add, { store: newStore, pure: true // 是一个函数 }); // 直接注入obj对象的地址 ``` ## storeController 处理 store storeController 是 store 的工具类,提供了一些对 store 的处理工具: - create 同 createStore - exist 判断目标 store 是否存在 - is 判断目标 store 是合理的 Store 的对象 - count 获取所有store个数 # 事件注入 ## 示例 ```ts import { createEvent } from "inject-provide"; const mainEvent = createEvent("Test"); @mainEvent.Subject() class Test { @mainEvent.Provider() sayHello() { console.log("hello, world"); } } mainEvent.controller.emit(); //hello,world ``` ## createEvent `createEvent` 函数会返回一个 `EventInjector` 类的一个实例,包含一个事件类装饰器、事件方法装饰器、事件控制器、事件注入库、事件标签装饰器。 ```ts declare class EventInjector { store: Store; controller: EventController; constructor(); Subject(): (...args: any[]) => (target: any) => void; Provide(): () => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void; Tag(): (tag?: string | undefined) => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void; } ``` ## Subject `Subject` 对一个类进行装饰,该类的方法可以成为事件的注入类 ```ts import { createEvent } from "inject-provide"; const mainEvent = createEvent("Test"); @mainEvent.Subject() class Test { } ``` ## Provider `Provider` 对一个类的实例方法进行装饰,该类的方法会被注入到事件控制器中 ```ts import { createEvent } from "inject-provide"; const mainEvent = createEvent("Test"); @mainEvent.Subject() class Test { @mainEvent.Provider() sayHello() { console.log("hello, world"); } } ``` ## Tag `Tag` 对一个类的实例方法进行装饰,该类的方法会被加上一个标签,可以被控制器筛选 ```ts import { createEvent } from "inject-provide"; const mainEvent = createEvent("Test"); @mainEvent.Subject() class Test { @mainEvent.Tag('main') @mainEvent.Provider() sayHello() { console.log("hello, world"); } } ``` 所有没有被 `Tag` 标记的所有方法在控制器库中的 `tag` 属性都为 `null`,所有不存在 `tag` 属性(为 `undefined`)的方法都不会被控制器识别。 ## controller `controller` 是一个类的控制器 ```ts import { createEvent } from "inject-provide"; const mainEvent = createEvent("Test"); @mainEvent.Subject() class Test { @mainEvent.Tag('main') @mainEvent.Provider() sayHello() { console.log("hello, world"); } @mainEvent.Provider() sayThanks() { console.log("Thanks"); } } mainEvent.controller.emit(); //hello,world, Thanks mainEvent.controller.tagSelector((tagName) => tagName.includes('m')).emit(); // only "hello, world" ``` `controller`的一些方法: ### emit 激活所有标记的事件 ### tagSelector 接受一个函数、字符串或者null,筛选出所有符合条件的事件。