olympus-r
Version:
一个力求简单易用的前端开发框架 #### 开发语言 TypeScript #### 核心架构 MVC #### 模块间通讯和解耦 采用事件机制,利用一个全局唯一的事件派发器进行模块间通讯,解耦模块间依赖 #### 表现层结构 使用桥接模式拆分接口与实现,达到一套核心驱动多套表现层的目的(目前支持DOM、Egret、PixiJS三种表现层),同时支持表现层的未来可扩展性 #### TypeScript装饰器注入 框架提供TypeScript装饰器注入功能,便捷获取托管对象。例如:
191 lines (190 loc) • 6.49 kB
JavaScript
import "../libs/Reflect";
import Dictionary from "../utils/Dictionary";
import { extendsClass } from "../utils/ObjectUtil";
/**
* @author Raykid
* @email initial_r@qq.com
* @create date 2017-09-13
* @modify date 2017-09-13
*
* 装饰器工具集
*/
// 用来判断是否支持Proxy
var hasProxy = false;
(window["Proxy"] && Proxy.revocable instanceof Function);
var instanceDict = new Dictionary();
function handleInstance(instance) {
var cls = instance.constructor;
cls = cls["__ori_constructor__"] || cls;
var funcs = instanceDict.get(cls);
if (funcs)
for (var _i = 0, funcs_1 = funcs; _i < funcs_1.length; _i++) {
var func = funcs_1[_i];
func(instance);
}
}
/**
* 包装一个类型,监听类型的实例化操作
*
* @export
* @param {IConstructor} cls 要监听构造的类型构造器
* @returns {IConstructor} 新的构造函数
*/
export function wrapConstruct(cls) {
if (hasProxy) {
// 使用Proxy监听类型构建
return new Proxy(cls, {
construct: function (target, args, newTarget) {
var result = Reflect["construct"](target, args, newTarget);
if (newTarget)
result.constructor = newTarget;
handleInstance(result);
return result;
}
});
}
else {
// 创建一个新的构造函数
var func;
try {
// 尝试保持原始类型的名称
eval('func = function ' + cls["name"] + '(){onConstruct.call(this, arguments)}');
}
catch (err) {
// 尝试失败,使用无名类型
func = onConstruct;
}
// 动态设置继承
extendsClass(func, cls);
// 为新的构造函数打一个标签,用以记录原始的构造函数
func["__ori_constructor__"] = cls;
// 为原始构造函数也打一个标签,用以记录新构造函数
cls["__wrap_constructor__"] = func;
// 返回新的构造函数
return func;
}
function onConstruct(args) {
// 恢复__proto__
Object.defineProperty(this, "__proto__", {
configurable: true,
enumerable: false,
writable: true,
value: cls.prototype
});
// 调用父类构造函数构造实例
cls.apply(this, args);
// 调用回调
handleInstance(this);
}
}
/**
* 如果传入的类有包装类,则返回包装类,否则返回其本身
*
* @export
* @param {IConstructor} cls 要获取包装类的类构造函数
* @returns {IConstructor}
*/
export function getConstructor(cls) {
return (cls["__wrap_constructor__"] || cls);
}
/**
* 监听类型的实例化
*
* @export
* @param {IConstructor} cls 要监听实例化的类
* @param {(instance?:any)=>void} handler 处理函数
*/
export function listenConstruct(cls, handler) {
cls = cls["__ori_constructor__"] || cls;
var list = instanceDict.get(cls);
if (!list)
instanceDict.set(cls, list = []);
if (list.indexOf(handler) < 0)
list.push(handler);
}
/**
* 移除实例化监听
*
* @export
* @param {IConstructor} cls 要移除监听实例化的类
* @param {(instance?:any)=>void} handler 处理函数
*/
export function unlistenConstruct(cls, handler) {
cls = cls["__ori_constructor__"] || cls;
var list = instanceDict.get(cls);
if (list) {
var index = list.indexOf(handler);
if (index >= 0)
list.splice(index, 1);
}
}
/**
* 监听类型销毁(如果能够销毁的话,需要类型具有dispose方法),该监听不需要移除
*
* @export
* @param {IConstructor} cls 要监听销毁的类
* @param {(instance?:any)=>void} handler 处理函数
*/
export function listenDispose(cls, handler) {
var dispose = cls.prototype.dispose;
// 判断类型是否具有dispose方法
if (dispose) {
// 替换dispose方法
cls.prototype.dispose = function () {
// 调用回调
handler(this);
// 调用原始dispose方法执行销毁
return dispose.apply(this, arguments);
};
}
}
/**
* 监听某个实例的某个方法调用,并插入逻辑
*
* @export
* @param {IConstructor|any} target 要监听的对象类型或实例
* @param {string} name 要监听调用的方法名
* @param {(instance:any, args?:any[])=>any[]|void} [before] 执行前调用的回调,如果有返回值则替换掉正式方法执行时的参数
* @param {(instance:any, args?:any[], result?:any)=>any} [after] 执行后调用的回调,可以接收正式方法的返回值,如果after有返回值则替换掉正式方法的返回值
* @param {boolean} [once=true] 是否是一次性监听,默认是true
*/
export function listenApply(target, name, before, after, once) {
if (once === void 0) { once = true; }
if (target instanceof Function)
// 是个类型,监听构建后再执行处理
listenConstruct(target, onGetInstance);
else
// 是个实例,直接执行处理
onGetInstance(target);
function onGetInstance(instance) {
// 篡改指定方法
var oriFunc = instance.hasOwnProperty(name) ? instance[name] : null;
instance[name] = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
// 调用回调
var tempArgs = before && before(instance, args);
// 替换参数
if (tempArgs)
args = tempArgs;
// 如果是一次性监听,则恢复原始方法
if (once) {
if (oriFunc)
instance[name] = oriFunc;
else
delete instance[name];
}
// 调用原始方法
var result = instance[name].apply(this, args);
// 调用回调
var tempResult = after && after(instance, args, result);
// 替换结果
if (tempResult)
result = tempResult;
// 返回结果
return result;
};
}
}