File tree Expand file tree Collapse file tree 8 files changed +159
-1
lines changed Expand file tree Collapse file tree 8 files changed +159
-1
lines changed Original file line number Diff line number Diff line change @@ -10,6 +10,7 @@ import {
10
10
Plugin ,
11
11
App ,
12
12
} from 'vue' ;
13
+ export { findService } from './utils' ;
13
14
14
15
export const POST_REACTIVE = 'METADATA_KEY_POST_REACTIVE' ;
15
16
export const MULTIPLE_POST_REACTIVE =
@@ -128,7 +129,12 @@ function getCurrentContainer() {
128
129
if ( instance ) {
129
130
const token = CONTAINER_TOKEN ;
130
131
const provides = instance . provides ;
131
- if ( provides && Object . prototype . hasOwnProperty . call ( provides , token ) ) {
132
+ const parentProvides = instance . parent && instance . parent . provides ;
133
+ if (
134
+ provides &&
135
+ provides !== parentProvides &&
136
+ Object . prototype . hasOwnProperty . call ( provides , token )
137
+ ) {
132
138
return provides [ token ] ;
133
139
}
134
140
} else {
Original file line number Diff line number Diff line change
1
+ import { interfaces } from 'inversify' ;
2
+ import { ComponentInternalInstance } from 'vue' ;
3
+
4
+ /**
5
+ * useService是从当前组件开始像父组件以及祖先组件查找服务实例
6
+ * findService是从当前组件【不包含当前组件】向子组件以及后代组件查找服务实例
7
+ * 可以通过component.container尝试获取该组件是否有绑定对应的inversify的container
8
+ * 然后通过container.isBound(token)来判断是否有绑定对应的服务
9
+ * 如果有绑定则通过container.get(token)来获取服务实例
10
+ * 注意component.subTree.children是当前组件的子组件
11
+ * 整个过程是一个递归的过程,因为子组件还有子组件,所以需要递归查找
12
+ * @param component ComponentInternalInstance 当前组件
13
+ * @param token interfaces.ServiceIdentifier<T> 服务标识
14
+ */
15
+ export function findService < T > (
16
+ component : ComponentInternalInstance ,
17
+ token : interfaces . ServiceIdentifier < T >
18
+ ) : T | undefined {
19
+ return ( component as any ) ;
20
+ // const children = component.subTree.children;
21
+ // if (children && Array.isArray(children)) {
22
+ // for (let i = 0; i < children.length; i++) {
23
+ // const child = children[i];
24
+ // if (child && child.component) {
25
+ // const container = child.component.container;
26
+ // if (container && container.isBound(token)) {
27
+ // return container.get(token);
28
+ // } else {
29
+ // return findService(child, token);
30
+ // }
31
+ // }
32
+ // }
33
+ // }
34
+ }
Original file line number Diff line number Diff line change
1
+ <script setup lang="ts">
2
+ import { declareProviders , useService } from ' ../../src/index' ;
3
+ import { ChildService } from ' ./ChildService' ;
4
+
5
+ declareProviders ([ChildService ]);
6
+ const childService = useService (ChildService );
7
+
8
+ defineExpose ({
9
+ childService ,
10
+ });
11
+ </script >
12
+
13
+ <template >
14
+ <div >
15
+ <div class =" child-count" >{{ childService.count }}</div >
16
+
17
+ <button
18
+ type =" button"
19
+ class =" btn-count-child"
20
+ @click =" childService.increaseCount()"
21
+ >
22
+ Add count child
23
+ </button >
24
+ </div >
25
+ </template >
Original file line number Diff line number Diff line change
1
+ export class ChildService {
2
+ public count = 1 ;
3
+
4
+ public increaseCount ( ) {
5
+ this . count ++ ;
6
+ }
7
+ }
Original file line number Diff line number Diff line change
1
+ <script setup lang="ts">
2
+ import {
3
+ declareProviders ,
4
+ useService ,
5
+ CURRENT_COMPONENT ,
6
+ } from ' ../../src/index' ;
7
+ import { DemoService } from ' ./DemoService' ;
8
+ import ChildComp from ' ./ChildComp.vue' ;
9
+ import { getCurrentInstance } from ' vue' ;
10
+
11
+ declareProviders ([DemoService ]);
12
+ const demoService = useService (DemoService );
13
+
14
+ const component1 = useService (CURRENT_COMPONENT );
15
+ const component2 = getCurrentInstance ();
16
+
17
+ defineExpose ({
18
+ demoService ,
19
+ component1 ,
20
+ component2 ,
21
+ });
22
+ </script >
23
+
24
+ <template >
25
+ <div >
26
+ <div class =" demo-count" >{{ demoService.count }}</div >
27
+
28
+ <button
29
+ type =" button"
30
+ class =" btn-count-demo"
31
+ @click =" demoService.increaseCount()"
32
+ >
33
+ Add count demo
34
+ </button >
35
+ </div >
36
+
37
+ <div class =" child-1-container" >
38
+ <div class =" child-1-wrapper" >
39
+ <ChildComp />
40
+ </div >
41
+ </div >
42
+
43
+ <div class =" child-2-container" >
44
+ <div class =" child-2-wrapper" >
45
+ <div class =" child-2-box" >
46
+ <ChildComp />
47
+ </div >
48
+ </div >
49
+ </div >
50
+ </template >
Original file line number Diff line number Diff line change
1
+ export class DemoService {
2
+ public count = 1 ;
3
+
4
+ public increaseCount ( ) {
5
+ this . count ++ ;
6
+ }
7
+ }
Original file line number Diff line number Diff line change
1
+ ## 测试场景
2
+
3
+ 验证循环依赖,LazyServiceIdentifier 也不能解决循环依赖的问题
4
+
5
+ 这是一个大问题,我以为属性注入器可以避免循环依赖已经是行业共识了,比如Spring中就是这么处理的。
6
+
7
+ 但是inversify居然不是这么处理的,显然是收集完所有属性之后才会放入缓存系统。
8
+
9
+ 比较简单的方案就是采用二级缓存,假设现在的缓存cache是最终的缓存结果。
10
+ 那么再增加一层tempCache,这个缓存只是临时存储实例化对象,方便被其他对象依赖时可以从缓存中获取该对象。
Original file line number Diff line number Diff line change
1
+ import 'reflect-metadata' ;
2
+ import { mount } from '@vue/test-utils' ;
3
+ import DemoComp from './DemoComp.vue' ;
4
+ import { ChildService } from './ChildService' ;
5
+ import { findService } from '../../src/index' ;
6
+
7
+ describe ( 'test19' , ( ) => {
8
+ it ( 'get DemoService instance' , async ( ) => {
9
+ const wrapper = mount ( DemoComp ) ;
10
+
11
+ expect ( wrapper . vm . component1 ) . toBe ( wrapper . vm . component2 ) ;
12
+
13
+ const childService = findService ( wrapper . vm . component1 , ChildService ) ;
14
+
15
+ // expect(childService).toBeInstanceOf(ChildService);
16
+
17
+ expect ( 1 ) . toBe ( 1 ) ;
18
+ } ) ;
19
+ } ) ;
You can’t perform that action at this time.
0 commit comments