前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Thinking--AOP思想在前端中的应用

Thinking--AOP思想在前端中的应用

作者头像
奋飛
发布2021-08-30 10:34:39
2270
发布2021-08-30 10:34:39
举报
文章被收录于专栏:Super 前端

Thinking系列,旨在利用10分钟的时间传达一种可落地的编程思想。

AOP

AOP(Aspect Oriented Programming),面向切面编程。其从主关注点中分离出横切关注点是面向侧面的程序设计的核心概念。分离关注点使得解决特定领域问题的代码从业务逻辑中独立出来。

具体到 Javascript 来说,由于语言本身的特性,天生就具有运行时动态插入逻辑的能力。重点在于在原函数上增加其他功能并不改变函数本身。

Spring中的Advice:前置通知(Before Advice)、后置通知(After Advice)、返回通知(After Return Advice)、环绕通知(Around Advice)、抛出异常后通知(After Throwing Advice)

javascript实现

代码语言:javascript
复制
Function.prototype.after = function (action) {
    // 保留当前函数,这里this指向运行函数
    var func = this
    // return 被包装过的函数,这里就可以执行其他功能了
    // 并且该方法挂在 Function.prototype 上,
    // 被返回的函数依然具有 after 属性,可以链式调用
    return function () {
        // 原函数执行,这里不考虑异步
        var result = func.apply(this, arguments)
        // 执行之后的操作
        action.apply(this, arguments)
        // 将执行结果返回
        return result
    }
}

Function.prototype.before = function (action) {
    var func = this
    return function () {
        action.apply(this, arguments)
        return func.apply(this, arguments)
    }
}
代码语言:javascript
复制
let beforeFn = function () {console.log('beforeFn')}
let afterFn = function () {console.log('afterFn')}
let fn = function () {console.log('fn')}
fn.before(beforeFn).after(afterFn)()	// beforeFn fn afterFn

问题陈述

两个模块(A、B),由于两个模块相似度很高,且其中一个模块(A)是历史模块(已开发完成);所以我们采用 extends 方式,来扩展开发新的模块(B)。

历史 A 模块

代码语言:javascript
复制
<el-button @click="submit">查询el-button>
<script>
export default {
  name: 'A',
  methods: {
    submit () {
    	/* 主逻辑业务 */
    }
  }
}
script>

现在,新模块(B)对于查询按钮的处理,需要发生变更,处理业务的同时需要发送相关日志。

对 A 模块进行改造,已适应新的方式

代码语言:javascript
复制
<el-button @click="submit">查询el-button>
<script>
export default {
  name: 'A',
  methods: {
    /* 将原有的逻辑业务代码进行抽离,便于新模块改造和沿用 */  
    submit () {
       this.submitReq()
    },
    submitReq () {
      /* 主逻辑业务 */
    }
  }
}  

新模块(B),覆盖默认submit 方法,进行日志处理,下面采用常规的静态代理模式

代码语言:javascript
复制
export default {
  name: 'B',
  extends: 'A',
  methods: {
    /* 覆盖原有submit方法,增加日志采集处理 */
    submit () {
      // 这个来自于 A 模块
      this.submitReq()
  		this.recordLogReg()
    },
		recordLogReg () {}
  }
}

解决方案

代码语言:javascript
复制
export default {
  name: 'B',
  extends: 'A',
  methods: {
    /* 覆盖原有submit方法,增加日志采集处理 */
    submit: this.submitReq.after(this.recordLogReg)(),
		recordLogReg () {
      /* 采集日志相关 */
    }
  }
}

每个函数变成了独立单元,可以随意组合,无需互相关联! 如果采用 class 写法,类的装饰器 decorator 也可以达到类似效果。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/06/02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • AOP
    • javascript实现
      • 问题陈述
        • 解决方案
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档