Skip to content

Commit c290096

Browse files
committed
component:directives, inheritAttrs, expose. Emit decorator
1 parent 34e247b commit c290096

File tree

4 files changed

+95
-11
lines changed

4 files changed

+95
-11
lines changed

readme.md

+28-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
Watch,
2020
Prop,
2121
Inject,
22+
Emit,
2223
Base,
2324
} from "vue-facing-decorator";
2425
import AnotherComponent from "./AnotherComponent.vue";
@@ -59,6 +60,19 @@ class Sup extends Base {
5960
},
6061
})
6162
export default class Comp extends Sup {
63+
//emit an event with name of method
64+
@Emit()
65+
eventName(arg: any) {
66+
return arg;
67+
}
68+
//emit an event with custom name and promise value
69+
//event will be emitted when promise resolved
70+
@Emit("eventCustomNamePromise")
71+
event2(arg: any) {
72+
return new Promise((resolver) => {
73+
resolver(arg);
74+
});
75+
}
6276
//create a ref
6377
@Ref
6478
readonly ref!: HTMLDivElement;
@@ -127,6 +141,8 @@ export default class Comp extends Sup {
127141
this.prop,
128142
this.provideAcientKeyAlias
129143
);
144+
this.eventName("eventName value");
145+
this.event2("eventCustomNamePromise value");
130146
}
131147
}
132148
```
@@ -138,10 +154,10 @@ import { defineComponent} from "vue";
138154
import AnotherComponent from "./AnotherComponent.vue";
139155
export default defineComponent({
140156
name: "MyComponent",
141-
components:{
142-
AnotherComponent
157+
components: {
158+
AnotherComponent,
143159
},
144-
emits: ["update:modelValue"],
160+
emits: ["update:modelValue", "eventName", "eventCustomNamePromise"],
145161
provide: {
146162
provideKey: "provideValue",
147163
},
@@ -166,6 +182,15 @@ export default defineComponent({
166182
method2() {
167183
console.log("method2");
168184
},
185+
eventName() {
186+
this.$emit("eventName", "eventName value");
187+
},
188+
async event2() {
189+
const value = await new Promise<any>((resolver) => {
190+
resolver("eventCustomNamePromise value");
191+
});
192+
this.$emit("eventCustomNamePromise", value);
193+
},
169194
},
170195
watch: {
171196
property: function (newv: string, oldv: string) {

src/component.ts

+27-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { defineComponent } from 'vue';
2-
import { toBaseReverse } from './utils'
2+
import { obtainSlot, toBaseReverse } from './utils'
33
import { build as optionComputed } from './option/computed'
44
import { build as optionData } from './option/data'
55
import { build as optionMethodsAndLifecycle } from './option/methodsAndLifecycle'
66
import { build as optionRef } from './option/ref'
77
import { build as optionWatch, WatchConfig } from './option/watch'
88
import { build as optionProps, PropsConfig } from './option/props'
99
import { build as optionInject, InjectConfig } from './option/inject'
10+
import { build as optionEmit } from './option/emit'
1011
export interface OptionBuilder {
1112
name?: string
1213
data?: Record<string, any>
@@ -16,6 +17,7 @@ export interface OptionBuilder {
1617
watch?: Record<string, WatchConfig>
1718
props?: Record<string, PropsConfig>
1819
inject?: Record<string, InjectConfig>
20+
1921
}
2022
export interface Cons { new(): any, prototype: any }
2123
function ComponentOption(cons: Cons) {
@@ -24,6 +26,7 @@ function ComponentOption(cons: Cons) {
2426
optionWatch(cons, optionBuilder)
2527
optionProps(cons, optionBuilder)
2628
optionInject(cons, optionBuilder)
29+
optionEmit(cons, optionBuilder)
2730
optionMethodsAndLifecycle(cons, optionBuilder)
2831
optionRef(cons, optionBuilder)
2932

@@ -37,7 +40,7 @@ function ComponentOption(cons: Cons) {
3740
computed: optionBuilder.computed,
3841
watch: optionBuilder.watch,
3942
props: optionBuilder.props,
40-
inject:optionBuilder.inject,
43+
inject: optionBuilder.inject,
4144
...optionBuilder.lifecycle
4245
}
4346
return raw as any
@@ -47,28 +50,44 @@ export function Component(arg: Cons | {
4750
name?: string
4851
emits?: string[]
4952
provide?: Record<string, any> | Function
50-
components?:Record<string,any>
53+
components?: Record<string, any>
54+
directives?: Record<string, any>;
55+
inheritAttrs?: boolean;
56+
expose?: string[];
5157
modifier?: (raw: any) => any
5258
}): any {
5359
if (typeof arg === 'function') {
5460
return defineComponent(ComponentOption(arg))
5561
}
5662
return function (cons: Cons) {
5763
let option = ComponentOption(cons)
64+
const slot = obtainSlot(cons.prototype)
5865
if (typeof arg.name !== 'undefined') {
5966
option.name = arg.name
6067
}
68+
69+
let emits = Array.from(slot.obtainMap('emits').keys())
6170
if (Array.isArray(arg.emits)) {
62-
option.emits = arg.emits
71+
emits = Array.from(new Set([...emits,...arg.emits]))
6372
}
64-
if(arg.components){
65-
option.components=arg.components
73+
option.emits = emits
74+
75+
76+
if (arg.components) {
77+
option.components = arg.components
6678
}
6779
if (arg.provide) {
6880
option.provide = arg.provide
6981
}
70-
71-
82+
if (arg.directives) {
83+
option.directives = arg.directives
84+
}
85+
if (arg.inheritAttrs) {
86+
option.inheritAttrs = arg.inheritAttrs
87+
}
88+
if (arg.expose) {
89+
option.expose = arg.expose
90+
}
7291
if (arg.modifier) {
7392
option = arg.modifier(option)
7493
}

src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export { decorator as Ref } from './option/ref'
44
export { decorator as Watch } from './option/watch'
55
export { decorator as Prop } from './option/props'
66
export { decorator as Inject } from './option/inject'
7+
export { decorator as Emit } from './option/emit'
78
import type {
89
ComponentInternalInstance,
910
ComponentPublicInstance,

src/option/emit.ts

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { Cons, OptionBuilder } from '../component'
2+
import { obtainSlot } from '../utils'
3+
import type { WatchCallback } from 'vue'
4+
export type EmitConfig = null | string
5+
export function decorator(key?: string) {
6+
7+
return function (proto: any, name: string) {
8+
const slot = obtainSlot(proto)
9+
let map = slot.obtainMap<Map<string, EmitConfig>>('emit');
10+
map.set(name, typeof key === 'undefined' ? null : key)
11+
}
12+
}
13+
14+
export function build(cons: Cons, optionBuilder: OptionBuilder) {
15+
optionBuilder.methods ??= {}
16+
const proto = cons.prototype
17+
const slot = obtainSlot(proto)
18+
const names = slot.obtainMap('emit')
19+
const emits = slot.obtainMap('emits')
20+
21+
if (names) {
22+
names.forEach((value, key) => {
23+
const eventName = value === null ? key : value
24+
emits.set(eventName, true)
25+
optionBuilder.methods![key] = async function (this: any) {
26+
27+
const ret = proto[key].apply(this, arguments)
28+
if (ret instanceof Promise) {
29+
const proRet = await ret
30+
this.$emit(eventName, proRet)
31+
}
32+
else {
33+
this.$emit(eventName, ret)
34+
}
35+
}
36+
})
37+
}
38+
39+
}

0 commit comments

Comments
 (0)