|
1 | | -import type { CommonToken } from '@kaokei/di'; |
2 | | -import type { |
3 | | - VNode, |
4 | | - VNodeChild, |
5 | | - VNodeArrayChildren, |
6 | | - VNodeNormalizedChildren, |
7 | | - ComponentInternalInstance, |
8 | | -} from 'vue'; |
9 | | -import { getContainer } from './component-container'; |
| 1 | +import type { CommonToken, Container } from '@kaokei/di'; |
10 | 2 |
|
11 | | -/** |
12 | | - * useService是从当前组件开始像父组件以及祖先组件查找服务实例 |
13 | | - * findService是从当前组件【不包含当前组件】向子组件以及后代组件查找服务实例 |
14 | | - * 可以通过component.container尝试获取该组件是否有绑定对应的inversify的container |
15 | | - * 然后通过container.isBound(token)来判断是否有绑定对应的服务 |
16 | | - * 如果有绑定则通过container.get(token)来获取服务实例 |
17 | | - * 注意component.subTree.children是当前组件的子组件 |
18 | | - * 整个过程是一个递归的过程,因为子组件还有子组件,所以需要递归查找 |
19 | | - * vnode.children |
20 | | - * vnode.component [node.component.subTree] |
21 | | - * vnode.suspense [node.suspense.activeBranch] |
22 | | - * vnode 判断所有vnode是否符合条件 |
23 | | - */ |
24 | | - |
25 | | -function nodesAsObject( |
26 | | - value: VNodeChild | VNodeArrayChildren |
27 | | -): value is VNodeArrayChildren | VNode { |
28 | | - return !!value && typeof value === 'object'; |
29 | | -} |
30 | | - |
31 | | -function walk<T>(vnode: VNode, token: CommonToken<T>, results: T[]): T[] { |
32 | | - if (vnode.component) { |
33 | | - const container = getContainer(vnode.component); |
34 | | - if (container && container.isCurrentBound(token)) { |
35 | | - results.push(container.get(token)); |
36 | | - } |
37 | | - } |
38 | | - // 优先遍历当前组件的子组件树 |
39 | | - walkChildren(vnode.children, token, results); |
40 | | - if (vnode.component) { |
41 | | - walk(vnode.component.subTree, token, results); |
42 | | - } |
43 | | - if (vnode.suspense && vnode.suspense.activeBranch) { |
44 | | - walk(vnode.suspense.activeBranch, token, results); |
45 | | - } |
46 | | - return results; |
47 | | -} |
48 | | - |
49 | | -function walkChildren<T>( |
50 | | - children: VNodeNormalizedChildren, |
| 3 | +function walk<T>( |
| 4 | + children: Set<Container> | undefined, |
51 | 5 | token: CommonToken<T>, |
52 | 6 | results: T[] |
53 | 7 | ): T[] { |
54 | | - if (children && Array.isArray(children)) { |
55 | | - const filteredNodes = children.filter(nodesAsObject); |
56 | | - filteredNodes.forEach((node: VNodeArrayChildren | VNode) => { |
57 | | - /* v8 ignore next 2 */ |
58 | | - if (Array.isArray(node)) { |
59 | | - walkChildren(node, token, results); |
60 | | - } else { |
61 | | - walk(node, token, results); |
| 8 | + if (children) { |
| 9 | + children.forEach(container => { |
| 10 | + if (container && container.isCurrentBound(token)) { |
| 11 | + results.push(container.get(token)); |
| 12 | + } |
| 13 | + if (container.children) { |
| 14 | + walk(container.children, token, results); |
62 | 15 | } |
63 | 16 | }); |
64 | 17 | } |
65 | 18 | return results; |
66 | 19 | } |
67 | 20 |
|
68 | | -/** |
69 | | - * @param component ComponentInternalInstance 当前组件 |
70 | | - * @param token CommonToken<T> 服务标识 |
71 | | - * @returns T | undefined 是从当前组件【不包含当前组件】的子组件以及后代组件中查找服务实例,返回第一个找到的服务实例 |
72 | | - */ |
73 | 21 | export function findService<T>( |
74 | 22 | token: CommonToken<T>, |
75 | | - component: ComponentInternalInstance |
| 23 | + container: Container |
76 | 24 | ): T | undefined { |
77 | 25 | const results: T[] = []; |
78 | | - walk(component.subTree, token, results); |
| 26 | + walk(container.children, token, results); |
79 | 27 | return results[0]; |
80 | 28 | } |
81 | 29 |
|
82 | | -/** |
83 | | - * @param component ComponentInternalInstance 当前组件 |
84 | | - * @param token CommonToken<T> 服务标识 |
85 | | - * @returns T[] 是从当前组件【不包含当前组件】的子组件以及后代组件中查找服务实例,返回所有找到的服务实例 |
86 | | - */ |
87 | 30 | export function findAllServices<T>( |
88 | 31 | token: CommonToken<T>, |
89 | | - component: ComponentInternalInstance |
| 32 | + container: Container |
90 | 33 | ): T[] { |
91 | 34 | const results: T[] = []; |
92 | | - walk(component.subTree, token, results); |
| 35 | + walk(container.children, token, results); |
93 | 36 | return results; |
94 | 37 | } |
0 commit comments