Skip to content

Commit c9699dc

Browse files
committed
feat: hook支持绑定多个
1 parent eaf73ed commit c9699dc

File tree

3 files changed

+74
-47
lines changed

3 files changed

+74
-47
lines changed

example/main.tsx

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import '@abraham/reflection'
2-
import { createCurrentInjector, Mut, VueComponent } from 'vue3-oop'
2+
import { createCurrentInjector, Hook, Mut, VueComponent } from 'vue3-oop'
33
import { createApp } from 'vue'
44
import 'ant-design-vue/dist/antd.css'
55
import { Layout, Menu } from 'ant-design-vue'
@@ -10,6 +10,16 @@ import { routes } from './router/routes'
1010
class App extends VueComponent {
1111
injector = createCurrentInjector([RouterStartService])
1212
@Mut() collapsed = false
13+
14+
@Hook('BeforeMount')
15+
before() {
16+
console.log(222)
17+
}
18+
19+
@Hook(['Mounted', 'BeforeMount'])
20+
mounted() {
21+
console.log(111)
22+
}
1323
render() {
1424
return (
1525
<Layout style={{ minHeight: '100vh' }}>

src/decorators/hook.ts

+55-42
Original file line numberDiff line numberDiff line change
@@ -29,57 +29,70 @@ type Lifecycle =
2929
| 'RenderTriggered'
3030
| 'ServerPrefetch'
3131

32-
export const Hook: HookDecorator = createDecorator('Hook')
32+
export const Hook: HookDecorator = createDecorator('Hook', true)
3333

3434
export interface HookDecorator {
35-
(lifecycle: Lifecycle): MethodDecorator
35+
(lifecycle: Lifecycle | Lifecycle[]): MethodDecorator
3636
MetadataKey: string | symbol
3737
}
3838

3939
function handler(targetThis: any) {
40-
const list = getProtoMetadata<Lifecycle>(targetThis, Hook.MetadataKey)
41-
if (!list || !list.length) return
40+
const list = getProtoMetadata<(Lifecycle | Lifecycle[])[]>(
41+
targetThis,
42+
Hook.MetadataKey
43+
)
44+
if (!list?.length) return
4245
for (const item of list) {
4346
let vueFn: any
44-
switch (item.options) {
45-
case 'BeforeMount':
46-
vueFn = onBeforeMount
47-
break
48-
case 'Mounted':
49-
vueFn = onMounted
50-
break
51-
case 'BeforeUpdate':
52-
vueFn = onBeforeUpdate
53-
break
54-
case 'Updated':
55-
vueFn = onUpdated
56-
break
57-
case 'BeforeUnmount':
58-
vueFn = onBeforeUnmount
59-
break
60-
case 'Unmounted':
61-
vueFn = onUnmounted
62-
break
63-
case 'Activated':
64-
vueFn = onActivated
65-
break
66-
case 'Deactivated':
67-
vueFn = onDeactivated
68-
break
69-
case 'ErrorCaptured':
70-
vueFn = onErrorCaptured
71-
break
72-
case 'RenderTracked':
73-
vueFn = onRenderTracked
74-
break
75-
case 'RenderTriggered':
76-
vueFn = onRenderTriggered
77-
break
78-
case 'ServerPrefetch':
79-
vueFn = onServerPrefetch
80-
break
47+
const doneLife: Record<string, true> = {}
48+
const options = item.options.slice()
49+
for (const option of options) {
50+
if (Array.isArray(option)) {
51+
options.push(...option)
52+
continue
53+
}
54+
if (doneLife[option]) continue
55+
switch (option) {
56+
case 'BeforeMount':
57+
vueFn = onBeforeMount
58+
break
59+
case 'Mounted':
60+
vueFn = onMounted
61+
break
62+
case 'BeforeUpdate':
63+
vueFn = onBeforeUpdate
64+
break
65+
case 'Updated':
66+
vueFn = onUpdated
67+
break
68+
case 'BeforeUnmount':
69+
vueFn = onBeforeUnmount
70+
break
71+
case 'Unmounted':
72+
vueFn = onUnmounted
73+
break
74+
case 'Activated':
75+
vueFn = onActivated
76+
break
77+
case 'Deactivated':
78+
vueFn = onDeactivated
79+
break
80+
case 'ErrorCaptured':
81+
vueFn = onErrorCaptured
82+
break
83+
case 'RenderTracked':
84+
vueFn = onRenderTracked
85+
break
86+
case 'RenderTriggered':
87+
vueFn = onRenderTriggered
88+
break
89+
case 'ServerPrefetch':
90+
vueFn = onServerPrefetch
91+
break
92+
}
93+
doneLife[option] = true
94+
vueFn(() => targetThis[item.key]())
8195
}
82-
vueFn(() => targetThis[item.key]())
8396
}
8497
}
8598

src/decorators/util.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,21 @@ export interface MetadataStore<T> {
1010
desc?: PropertyDescriptor | null
1111
}
1212

13-
export function createDecorator<T = void>(name: string) {
13+
export function createDecorator<T = void>(name: string, allowRepeat = false) {
1414
const metaName = `VUE3-OOP_${name.toUpperCase()}`
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>[] =
18+
let list: MetadataStore<T | T[]>[] =
1919
Reflect.getMetadata(MetadataKey, target) || []
2020
list = list.slice()
2121
const hasItem = list.find((k) => k.key === key)
22-
if (!hasItem) list.push({ key, options })
23-
else hasItem.options = options
22+
if (!hasItem) {
23+
list.push({ key, options: allowRepeat ? [options] : options })
24+
} else {
25+
if (!allowRepeat) hasItem.options = options
26+
else if (Array.isArray(hasItem.options)) hasItem.options.push(options)
27+
}
2428
Reflect.defineMetadata(MetadataKey, list, target)
2529
}
2630
}

0 commit comments

Comments
 (0)