Skip to content

Commit 04ca97b

Browse files
committed
createDecorator
1 parent 506739a commit 04ca97b

File tree

11 files changed

+139
-1
lines changed

11 files changed

+139
-1
lines changed

docs/en/_sidebar.md

+2
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,7 @@
2020
- TSX
2121
- [TSX render](/en/tsx/tsx-render/tsx-render.md)
2222
- [Attribute types](/en/tsx/attribute-types/attribute-types.md)
23+
- Custom Decorator
24+
- [Custom Decorator](/en/custom/custom.md)
2325
- Compatibility
2426
- [reflect-metadata](/en/compatibility/reflect-metadata/reflect-metadata.md)

docs/en/custom/code-usage.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { createDecorator, Component, Vue } from 'vue-facing-decorator'
2+
3+
function Log(prefix: string) {
4+
return createDecorator(function (options, key) {
5+
const old = options.methods?.[key]
6+
if (!old) {
7+
throw 'not found'
8+
}
9+
options.methods[key] = function (...args: any[]) {
10+
old.apply(this, args)
11+
}
12+
})
13+
}
14+
15+
@Component
16+
export default class Comp extends Vue {
17+
@Log('prefix')
18+
method() {
19+
20+
}
21+
}

docs/en/custom/custom.md

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## Usage
2+
3+
Use `createDecorator` to build your own decorators.
4+
5+
If you are a package author, install vue-facing-decorator as `devDependecies` and mark it in `peerDependencies`.
6+
7+
`createDecorator` received a creator function, which accepts tow parameters:
8+
1. Generated vue options component, you can modify it to implement anything you want.
9+
2. The key of class property(or method) which decorator decorated.
10+
11+
[](./code-usage.ts ':include :type=code typescript')

docs/zh-cn/_sidebar.md

+2
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,7 @@
2020
- TSX
2121
- [TSX](/zh-cn/tsx/tsx-render/tsx-render.md)
2222
- [属性类型](/zh-cn/tsx/attribute-types/attribute-types.md)
23+
- 自定义装饰器
24+
- [自定义装饰器](/zh-cn/custom/custom.md)
2325
- 兼容性
2426
- [reflect-metadata](/zh-cn/compatibility/reflect-metadata/reflect-metadata.md)

docs/zh-cn/custom/code-usage.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { createDecorator, Component, Vue } from 'vue-facing-decorator'
2+
3+
function Log(prefix: string) {
4+
return createDecorator(function (options, key) {
5+
const old = options.methods?.[key]
6+
if (!old) {
7+
throw 'not found'
8+
}
9+
options.methods[key] = function (...args: any[]) {
10+
old.apply(this, args)
11+
}
12+
})
13+
}
14+
15+
@Component
16+
export default class Comp extends Vue {
17+
@Log('prefix')
18+
method() {
19+
20+
}
21+
}

docs/zh-cn/custom/custom.md

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## 用法
2+
3+
使用 `createDecorator` 构建你自己的装饰器.
4+
5+
如果你是一位包作者,请将 vue-facing-decorator 安装到 `devDependecies` 中,并在 `peerDependencies` 中列出它。
6+
7+
`createDecorator` 接收一个函数,这个函数接收两个参数:
8+
1. 生成的Vue options组件,你可以修改这个参数来实现你想实现的功能。
9+
2. 装饰器所装饰的类属性(或方法)名。
10+
11+
[](../../en//custom/code-usage.ts ':include :type=code typescript')

src/component.ts

+8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { build as optionInject } from './option/inject'
1111
import { build as optionEmit } from './option/emit'
1212
import { build as optionVModel } from './option/vmodel'
1313
import { build as optionAccessor } from './option/accessor'
14+
import { CustomRecords } from './custom/custom'
1415
import type { SetupContext } from 'vue';
1516
import type { OptionBuilder } from './optionBuilder'
1617
import type { VueCons } from './index'
@@ -33,6 +34,7 @@ function ComponentOption(cons: Cons, extend?: any) {
3334
optionMethodsAndHooks(cons, optionBuilder)//after Ref Computed
3435
optionAccessor(cons, optionBuilder)
3536

37+
3638
const setupFunction: OptionSetupFunction | undefined = optionBuilder.setup ? function (props, ctx) {
3739
return optionBuilder.setup!(props, ctx)
3840
} : undefined
@@ -85,6 +87,12 @@ function buildComponent(cons: Cons, arg: ComponentOption, extend?: any): any {
8587
emits = Array.from(new Set([...emits, ...arg.emits]))
8688
}
8789
option.emits = emits
90+
91+
92+
CustomRecords.forEach(rec => {
93+
rec.creator.apply({}, [option, rec.key])
94+
})
95+
8896
if (arg.setup) {
8997
if (!option.setup) {
9098
option.setup = arg.setup

src/custom/custom.ts

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
type Creator = { (options: any, key: string): void }
2+
interface Record {
3+
key: string
4+
creator: Creator
5+
}
6+
7+
// const CustomDecorators: CustomDecorator[] = []
8+
export const CustomRecords: Record[] = []
9+
10+
export function createDecorator(creator: Creator) {
11+
return function (proto: any, key: string) {
12+
CustomRecords.push({
13+
key,
14+
creator
15+
})
16+
}
17+
}
18+
19+

src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export { decorator as Emit } from './option/emit'
88
export { decorator as VModel, decorator as Model } from './option/vmodel'
99
export { decorator as Vanilla } from './option/vanilla'
1010
export { decorator as Hook } from './option/methodsAndHooks'
11+
export { createDecorator } from './custom/custom'
1112
export { mixins } from './mixins'
1213
import type { ComponentPublicInstance } from 'vue'
1314
import type { OptionBuilder } from './optionBuilder'

test/custom/custom.ts

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
2+
import { expect } from 'chai';
3+
import 'mocha';
4+
import { Component, Base, createDecorator } from '../../dist'
5+
6+
function CustomDeco(param?: String) {
7+
return createDecorator(function (options: any, key: string) {
8+
options.methods ??= {}
9+
const old: Function = options.methods[key]
10+
if (!old) {
11+
throw 'method not found'
12+
}
13+
options.methods[key] = function (...args: any[]) {
14+
return `${old.apply(this, args)} ${param}`
15+
}
16+
})
17+
}
18+
19+
@Component
20+
export class Comp extends Base {
21+
@CustomDeco('DecoParam')
22+
method(this: any, param: string) {
23+
this.contextKey = 'contextValue'
24+
return `method return value ${param}`
25+
}
26+
}
27+
28+
const CompContext = Comp as any
29+
30+
describe('create decorator',
31+
() => {
32+
it('default', () => {
33+
expect('function').to.equal(typeof (CompContext.methods?.method))
34+
const context: any = {}
35+
const ret = CompContext.methods?.method.apply(context, ['Param'])
36+
expect('contextValue').to.equal(context.contextKey)
37+
expect('method return value Param DecoParam').to.equal(ret)
38+
})
39+
}
40+
)
41+
export default {}

test/test.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ import './feature/componentExtends'
1919
import './feature/extends'
2020
import './feature/mixinsFunction'
2121

22+
import './tsx/attributeTypes'
2223

23-
import './tsx/attributeTypes'
24+
import './custom/custom'

0 commit comments

Comments
 (0)