前端 AOP 编程思想体现

AOP 介绍

面向切片编程(AOP)是 java 常用编程思想,它的作用是在某个函数上进行切割,可以在函数执行前/后添加其他逻辑代码。

前/后添加其他逻辑代码,体现在哪?

场景实战

有这样一个控制器,界面呈现呈现数据过程中增加 loading 效果

class Controllers {

loading: boolean = false;

constructor() {

this.getData();

}

private getData() {

new Promise(() => {}).then(() => {

...

})

}

}

分析业务场景可以发现,过程中增加 loading 效果,就是在获取数据方法 getData 获取数据之前,增加 loading=true,在 getData 获取数据之后,增加 loading = false;

常规操作

class Controllers {

loading: boolean = false;

constructor() {

this.getData();

this.getData1();

this.getData2();

}

private getData() {

this.loading = true;

new Promise(() => {}).then(() => {

// ...

}).finally(() => {

this.loading = false;

})

}

private getData1() {

this.loading = true;

new Promise(() => {}).then(() => {

// ...

}).finally(() => {

this.loading = false;

})

}

private getData2() {

this.loading = true;

new Promise(() => {}).then(() => {

// ...

}).finally(() => {

this.loading = false;

})

}

}

这样在 getData 中增加和获取数据不相关的业务操作,真的好吗?

-- 在方法中增加和该方法的逻辑不相关代码行为,被称为:方法玷污

是不是所有的呈现数据相关的业务,都需要手动增加 this.loading ?

回调复用

写一个回调,来批量实现 loading 改变的效果

function loadingFunc(T: any, fn: Function) {

return async function(...args: any[]) {

(T as any)['loading'] = true;

await fn.apply(T, args);

(T as any)['loading'] = false;

}

}

class Controllers {

loading: boolean = false;

constructor() {

loadingFunc(this, this.getData)();

loadingFunc(this, this.getData1)();

loadingFunc(this, this.getData2)();

}

private getData() {

new Promise(() => {}).then(() => {

// ...

})

}

private getData1() {

new Promise(() => {}).then(() => {

// ...

})

}

private getData2() {

new Promise(() => {}).then(() => {

// ...

})

}

}

方法拦截器

// 前置拦截器

(T as any)['loading'] = true;

await fn.apply(T, args);

// 后置拦截器

(T as any)['loading'] = false;

我们可以称呼这样的行为是:方法拦截器。在原生方法调用之前,我们处理了一些业务逻辑,在原生方法调用之后,紧接着处理了一些业务逻辑。通过方法拦截器,消除了方法玷污,实现了方法复用。

装饰者模式

装饰者模式的精髓在于装饰,引用《天下长河》中康熙对传教士的一句台词:“不要试图毁灭什么,而要想着为这片土地增加什么”,这就是装饰的意思。我们使用一个方法,来装饰目标函数,为目标函数,带来了前置拦截器和后置拦截器,这是装饰者模式,也是面向切面编程思想的体现。

Typescript 装饰器实现方法拦截器

function Loading(paramsValue: any) {

return function (targetClassPrototype: any, methodName: any, methodDecri: PropertyDescriptor) {

let targetMethodSave = methodDecri.value;

methodDecri.value = async function (...args: any[]) {

(this as any)[paramsValue] = true;

await targetMethodSave.apply(this, args);

(this as any)[paramsValue] = false;

}

}

}

class Controllers {

loading: boolean = false;

constructor() {

this.getData();

}

@Loading('loading')

private getData() {

new Promise(() => {}).then(() => {

// ...

})

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值