在 vfd 中提供了自定义装饰器的封装,接下来就通过实现一个 AOP 开发中一个典型的日志输出装饰器。
接下来通过改造 14组合式API应用 中的代码来实现一个打印当前执行的方法名称的日志输出装饰器。
vue
<script lang="ts">
import { Component, Setup, Vue } from 'vue-facing-decorator'
import { useRouter, Router } from 'vue-router'
import Log from './decorator/index';
@Component
export default class App extends Vue {
@Setup(() => useRouter())
router!: Router;
@Log()
goto(path: string) {
this.router.push({ path });
}
}
</script>
<script lang="ts">
import { Component, Setup, Vue } from 'vue-facing-decorator'
import { useRouter, Router } from 'vue-router'
import Log from './decorator/index';
@Component
export default class App extends Vue {
@Setup(() => useRouter())
router!: Router;
@Log()
goto(path: string) {
this.router.push({ path });
}
}
</script>
在 vfd 模块中导出 createDecorator
,createDecorator
需要接收一个回调函数,在这个回调函数被触发时,可以通过它的参数获取到 组件的选项(方便进行修改),还会获得装饰器所在的类属性或方法的名称。
在下面实现的装饰器中是一个典型的函数扩展,首先会将 xx 函数的功能保存到 original ,接着就是用一个新的函数来重写原先的功能,在新编写的函数中会使用 apply 对原函数的功能进行执行。这样就可以在不丢失原有函数功能的前提下对函数进行扩展了。
typescript
import { createDecorator } from 'vue-facing-decorator';
function Log() {
return createDecorator(
function (options, key) {
const original = options.methods?.[key];
if (original) {
options.methods[key] = function (...args: any[]) {
original.apply(this, args);
console.log(`The ${key} function is executed`)
}
}
},
{
preserve: true,
}
);
}
export default Log;
import { createDecorator } from 'vue-facing-decorator';
function Log() {
return createDecorator(
function (options, key) {
const original = options.methods?.[key];
if (original) {
options.methods[key] = function (...args: any[]) {
original.apply(this, args);
console.log(`The ${key} function is executed`)
}
}
},
{
preserve: true,
}
);
}
export default Log;
[^注]: 需要装饰器所描述的类属性或类方法需要再装饰器生效前保留,需要开启 preserve 选项,在上面的案例中很显然我们是需要得到所描述的方法的,故进行了开启。