Skip to content

Commit e601189

Browse files
committed
feat: 增加getCurrentInjector,在外部服务中获取注射器
1 parent e1160f4 commit e601189

16 files changed

+203
-182
lines changed

docs/guide/api.md

+15
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ class Foo extends VueComponent {
103103

104104
获取当前的应用app
105105

106+
## getCurrentInjector
107+
108+
在外部服务中获取当前的最近一级的注射器
109+
110+
106111
# 类型
107112

108113
## ComponentProps
@@ -122,5 +127,15 @@ class Foo extends VueComponent<FooProps> {
122127
}
123128
```
124129

130+
## ComponentSlots
131+
132+
在render函数中定义slots的时候用到
133+
134+
```tsx
135+
const a: ComponentSlots<Foo> = {
136+
137+
}
138+
```
139+
125140

126141

example/count.service.ts

-15
This file was deleted.

example/example.tsx

-34
This file was deleted.

example/form.tsx

-1
This file was deleted.

example/main.tsx

+30-64
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,51 @@
11
import '@abraham/reflection'
2-
import { Component, Computed, Hook, Mut, VueComponent, VueService } from 'vue3-oop'
2+
import {
3+
Component,
4+
getCurrentInjector,
5+
Hook,
6+
VueComponent,
7+
VueService,
8+
} from 'vue3-oop'
9+
import type { Directive } from 'vue'
310
import { createApp } from 'vue'
11+
import { focusDirective } from './focus.directive'
12+
import { Injector } from 'injection-js'
413

5-
const debounce = (delay: number) => {
6-
let timeout: number | undefined
7-
return (track: any, trigger: any) => {
8-
let value: any
9-
return {
10-
get() {
11-
track()
12-
return value
13-
},
14-
set(newValue: any) {
15-
clearTimeout(timeout)
16-
timeout = window.setTimeout(() => {
17-
value = newValue
18-
trigger()
19-
}, delay)
20-
},
21-
}
22-
}
23-
}
24-
25-
class CountService extends VueService {
26-
@Mut() count = 1
14+
class OutService extends VueService {
15+
injector = getCurrentInjector()
2716
}
2817

29-
class Home extends VueComponent {
30-
@Mut(debounce(1000)) _count = ''
31-
32-
@Mut() obj = { name: 123 }
33-
34-
@Computed()
35-
get double() {
36-
return this._count
18+
@Component()
19+
class App extends VueComponent {
20+
static directives: Record<string, Directive> = {
21+
focus: focusDirective,
3722
}
38-
set double(val: string) {
39-
this._count = val.toUpperCase()
23+
constructor(private injector: Injector) {
24+
super()
4025
}
4126

42-
@Hook('Mounted')
43-
mounted() {
44-
console.log('mounted')
45-
}
27+
outService = new OutService()
4628

47-
render() {
48-
console.log(this.obj)
49-
console.log('render')
50-
return <input type="text" v-model={this.double} />
29+
@Hook('Mounted')
30+
mount() {
31+
console.log(
32+
this.injector,
33+
this.outService.injector,
34+
this.injector === this.outService.injector
35+
)
5136
}
52-
}
5337

54-
@Component()
55-
class Home1 extends Home {
56-
constructor(private cs: CountService) {
57-
super()
58-
console.log(cs)
59-
}
60-
@Mut() count1 = 111
6138
render() {
6239
return (
6340
<div>
64-
<h5 onClick={() => this.cs.count++}>{this.cs.count}</h5>
65-
<h2 onClick={() => this.count1++}>1111{this.count1}</h2>
66-
{super.render()}
41+
<div>
42+
指令:
43+
<input type="text" v-focus />
44+
</div>
6745
</div>
6846
)
6947
}
7048
}
7149

72-
class App extends VueComponent {
73-
render() {
74-
return (
75-
<>
76-
<Home1></Home1>
77-
<Home1></Home1>
78-
<Home1></Home1>
79-
</>
80-
)
81-
}
82-
}
83-
8450
const app = createApp(App)
8551
app.mount('#app')

example/size.service.ts

-36
This file was deleted.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
"access": "public"
108108
},
109109
"peerDependencies": {
110-
"@abraham/reflection": "^0.8.0",
110+
"@abraham/reflection": "*",
111111
"injection-js": "^2.4.0",
112112
"vue": "^3.2.20"
113113
},

src/decorators/link.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ export interface LinkDecorator {
99
}
1010

1111
function handler(targetThis: Record<any, any>) {
12-
const list = getProtoMetadata<string | undefined>(targetThis, Link.MetadataKey)
12+
const list = getProtoMetadata<string | undefined>(
13+
targetThis,
14+
Link.MetadataKey
15+
)
1316
if (!list || !list.length) return
1417
for (const item of list) {
1518
const { key, options } = item

src/decorators/util.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export function createDecorator<T = void>(name: string) {
1515
const MetadataKey = createSymbol(metaName)
1616
const decoratorFn: DecoratorFn<T> = function (options: T) {
1717
return function (target: any, key: string | symbol) {
18-
let list: MetadataStore<T>[] = Reflect.getMetadata(MetadataKey, target) || []
18+
let list: MetadataStore<T>[] =
19+
Reflect.getMetadata(MetadataKey, target) || []
1920
list = list.slice()
2021
const hasItem = list.find((k) => k.key === key)
2122
if (!hasItem) list.push({ key, options })
@@ -31,7 +32,11 @@ export function createDecorator<T = void>(name: string) {
3132
})
3233
return decoratorFn
3334
}
34-
export function getProtoMetadata<T = void>(target: any, key: symbol | string, withDesc = false): MetadataStore<T>[] {
35+
export function getProtoMetadata<T = void>(
36+
target: any,
37+
key: symbol | string,
38+
withDesc = false
39+
): MetadataStore<T>[] {
3540
const proto = Object.getPrototypeOf(target)
3641
if (!proto) return []
3742
const res: MetadataStore<any>[] = Reflect.getMetadata(key, proto) || []
@@ -40,7 +45,10 @@ export function getProtoMetadata<T = void>(target: any, key: symbol | string, wi
4045
}
4146
return res
4247
}
43-
export function getDeepOwnDescriptor(proto: any, key: string | symbol): PropertyDescriptor | null {
48+
export function getDeepOwnDescriptor(
49+
proto: any,
50+
key: string | symbol
51+
): PropertyDescriptor | null {
4452
if (!proto) return null
4553
const desc = Object.getOwnPropertyDescriptor(proto, key)
4654
if (desc) return desc

src/di/index.ts

+41-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
1-
import type { ClassProvider, Provider, ResolvedReflectiveProvider, TypeProvider } from 'injection-js'
2-
import { Injectable, InjectionToken, ReflectiveInjector, SkipSelf } from 'injection-js'
1+
import type {
2+
ClassProvider,
3+
Provider,
4+
ResolvedReflectiveProvider,
5+
TypeProvider,
6+
} from 'injection-js'
7+
import {
8+
Injectable,
9+
InjectionToken,
10+
ReflectiveInjector,
11+
SkipSelf,
12+
} from 'injection-js'
313
import type { InjectionKey } from 'vue'
414
import { getCurrentInstance, inject, provide } from 'vue'
515
import { createSymbol } from '../helper'
616

7-
export const InjectorKey: InjectionKey<ReflectiveInjector> = createSymbol('VUE3-OOP_ReflectiveInjector') as symbol
17+
export const InjectorKey: InjectionKey<ReflectiveInjector> = createSymbol(
18+
'VUE3-OOP_ReflectiveInjector'
19+
) as symbol
820

921
const MetadataKey = createSymbol('VUE3-OOP_Component')
1022
const MetadataProviderKey = createSymbol('VUE3-OOP_ResolveProviders')
@@ -51,8 +63,14 @@ export function resolveComponent(target: { new (...args: []): any }) {
5163
// 如果没有使用 injection-js 则不创建注入器
5264
if (!Reflect.getMetadata('annotations', target)) return new target()
5365
const parent = inject(InjectorKey, undefined)
54-
let resolveProviders = Reflect.getOwnMetadata<ResolvedReflectiveProvider[]>(MetadataProviderKey, target)
55-
const options: ComponentOptions | undefined = Reflect.getOwnMetadata(MetadataKey, target)
66+
let resolveProviders = Reflect.getOwnMetadata<ResolvedReflectiveProvider[]>(
67+
MetadataProviderKey,
68+
target
69+
)
70+
const options: ComponentOptions | undefined = Reflect.getOwnMetadata(
71+
MetadataKey,
72+
target
73+
)
5674
if (!resolveProviders || options?.stable === false) {
5775
// 依赖
5876
let deps: Provider[] = [target]
@@ -71,7 +89,10 @@ export function resolveComponent(target: { new (...args: []): any }) {
7189
// 缓存解析过的依赖, 提高性能
7290
Reflect.defineMetadata(MetadataProviderKey, resolveProviders, target)
7391
}
74-
const injector = ReflectiveInjector.fromResolvedProviders(resolveProviders, parent)
92+
const injector = ReflectiveInjector.fromResolvedProviders(
93+
resolveProviders,
94+
parent
95+
)
7596
if (options?.globalStore) {
7697
// 如果作为全局的服务,则注入到根上面
7798
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -103,7 +124,11 @@ export function resolveDependencies(inputs: Provider[]) {
103124
const deps = new Set<Provider>()
104125

105126
function resolver(klass: Provider) {
106-
if (deps.has(klass) || noConstructor.find((k) => k !== klass && k.provide === klass)) return
127+
if (
128+
deps.has(klass) ||
129+
noConstructor.find((k) => k !== klass && k.provide === klass)
130+
)
131+
return
107132
deps.add(klass)
108133
const resolves = ReflectiveInjector.resolve([klass])
109134
for (const item of resolves) {
@@ -127,3 +152,12 @@ export function resolveDependencies(inputs: Provider[]) {
127152

128153
return Array.from(deps)
129154
}
155+
156+
/**
157+
* 获取当前的注射器,可用于外部使用
158+
*/
159+
export function getCurrentInjector(): ReflectiveInjector {
160+
const instance = getCurrentInstance()
161+
// @ts-ignore
162+
return instance.provides[InjectorKey] || inject(InjectorKey)
163+
}

0 commit comments

Comments
 (0)