Arale aspect切面编程源码解析

本文深入探讨了Arale框架的切面编程实现,通过源码分析,揭示了如何利用该技术优雅地控制方法执行顺序。通过实例,读者将理解切面编程在前端开发中的应用及其优势。
摘要由CSDN通过智能技术生成

切面编程能让你有效的控制方法的执行顺序。举个例子:

var Dialog = Base.extend({
    ...

    show: function() {
        console.log(2);
        this.element.show();
    },

    ...
});

var dialog = new Dialog();

dialog.before('show', function() {
    console.log(1);
});

dialog.after('show', function() {
    console.log(3);
});

dialog.show(); // ==> 1, 2, 3

这里有一个需要注意的点就是,如果before方法返回的值为false,那么函数本身以及after方法的回调将不再执行。

var Dialog = Base.extend({
    ...

    show: function() {
        console.log(2);
        this.element.show();
    },

    ...
});

var dialog = new Dialog();

dialog.before('show', function() {
    console.log(1);
    return false;
});

dialog.after('show', function() {
    console.log(3);
});

dialog.show(); // ==> 1

其源码注释如下。因为这里的aspect是给Base类使用的,Base继承了Events,所以它有on,trigger等方法。

// this指向Base实例
// 在指定方法执行前,先执行 callback
// context是callback的执行环境
exports.before = function(methodName, callback, context) {
	return weave.call(this, 'before', methodName, callback, context);
};
// 在指定方法执行后,再执行 callback
exports.after = function(methodName, callback, context) {
	return weave.call(this, 'after', methodName, callback, context);
};
// Helpers
// -------
// 以空格来分隔方法名
var eventSplitter = /\s+/;
function weave(when, methodName, callback, context) {
	// 将方法名转化为数组
	var names = methodName.split(eventSplitter);
	var name, method;
	while (name = names.shift()) {
		method = getMethod(this, name);
		// 如果没有wrap则执行wrap
		if (!method.__isAspected) {
			wrap.call(this, name);
		}
		// 继承了Events
		this.on(when + ':' + name, callback, context);
	}
	return this;
}
// 从host宿主中取得方法名对应的方法(若是取不到则做报错处理)
function getMethod(host, methodName) {
	var method = host[methodName];
	if (!method) {
		throw new Error('Invalid method name: ' + methodName);
	}
	return method;
}
// wrap方法
function wrap(methodName) {
	// 保存方法名对应的方法
	var old = this[methodName];
	// 重新定义该方法
	this[methodName] = function() {
		var args = Array.prototype.slice.call(arguments);
		var beforeArgs = ['before:' + methodName].concat(args);
		// prevent if trigger return false
		// 如果before方法返回了false,那么就不再执行原方法以及after后的方法
		if (this.trigger.apply(this, beforeArgs) === false) return;
		var ret = old.apply(this, arguments);
		// 将原方法执行后的返回值也传给after后的执行的方法
		var afterArgs = ['after:' + methodName, ret].concat(args);
		this.trigger.apply(this, afterArgs);
		return ret;
	};
	// 给对应的方法名传递特殊参数,防止二次wrap
	this[methodName].__isAspected = true;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值