0.3.8 • Published 4 years ago

inject-provide v0.3.8

Weekly downloads
2
License
ISC
Repository
-
Last release
4 years ago

Inject-Provide

inject-provide 是一个极简洁的 nodejs 注入框架,运行过程中需要装饰器的支持,建议使用 TypeScript 作为运行环境。

安装

 npm install inject-provide --save

基本使用

inject-provide 的使用方法非常简单,只有 7 个 API。

  • 注入: Inject, AutoInjected

  • 提供:Provide, Offer

  • 注册:createStore

  • 默认库:rootStore

  • 注入库工具类:storeController

  • 事件处理:createEvent

创建注入库

import { createStore } from "inject-provide";

export newStore = createStore("newStore");

这一步创建过程是可选的,inject-provide 已经构建了一个默认的根注入库,即 rootStore,在所有不指明的注入 store 都会默认注入到 rootStore中。

提供类

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 参数数组中,在提交到注入库的时候会被初始化。

使用注入服务

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

使用自动注入

import { AutoInject } from "inject-provide";
import { UseCar } from "./use-car";

const result = AutoInject(UseCar);
result.getCarName(); //BMW

进阶技巧

参数注入

在构造函数中,如果有多个需要注入和不注入的参数,要把需要注入的参数放在前面

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();
	}
}

非注入的处理

自动注入时,不在注入服务中的参数按顺序写在后面

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, 可以使用直接提供服务的方式,为其他类型提供注入功能

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 参数,来表明这是一个简单的函数

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个数

事件注入

示例

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 类的一个实例,包含一个事件类装饰器、事件方法装饰器、事件控制器、事件注入库、事件标签装饰器。

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 对一个类进行装饰,该类的方法可以成为事件的注入类

import { createEvent } from "inject-provide";

const mainEvent = createEvent("Test");

@mainEvent.Subject()
class Test {
	
}

Provider

Provider 对一个类的实例方法进行装饰,该类的方法会被注入到事件控制器中

import { createEvent } from "inject-provide";

const mainEvent = createEvent("Test");

@mainEvent.Subject()
class Test {
	@mainEvent.Provider()
	sayHello() {
		console.log("hello, world");
	}
}

Tag

Tag 对一个类的实例方法进行装饰,该类的方法会被加上一个标签,可以被控制器筛选

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 是一个类的控制器

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,筛选出所有符合条件的事件。

0.3.8

4 years ago

0.3.7

4 years ago

0.3.6

4 years ago

0.3.5

4 years ago

0.3.4

4 years ago

0.3.0

4 years ago

0.3.1

4 years ago

0.3.3

4 years ago

0.2.4

4 years ago

0.2.1

4 years ago

0.2.0

4 years ago

0.1.1

4 years ago

0.1.0

4 years ago

0.0.4

4 years ago

0.0.3

4 years ago

0.0.2

4 years ago

0.0.1

4 years ago