aralejs / base Goto Github PK
View Code? Open in Web Editor NEWBase Class
Home Page: aralejs.org/base/
Base Class
Home Page: aralejs.org/base/
现在 initAttrs
有两个参数 this.initAttrs(config, dataAttrsConfig)
,但 dataAttrsConfig
最后也是被 merge 到 config
的,所以我觉得第二个参数没有必要,完全可以外部处理完后再传入 config。
overlay.before('show.overlay', callback);
getMethod 这里可以做一下处理
function getMethod(host, methodName) {
var method = host[methodName];
...
}
http://aralejs.org/base/docs/attribute.html
/* panel.js */
define(function(require, exports, module) {
var Base = require('arale/base/1.1.1/base');
var $ = require('$');
var Panel = Base.extend({
attrs: {
element: {
value: '#test',
readOnly: true
},
color: '#fff',
size: {
width: 100,
height: 100
},
x: 200,
y: 200,
xy: {
getter: function() {
return this.get('x') + this.get('y');
},
setter: function(val) {
this.set('x', val[0]);
this.set('y', val[1]);
}
}
},
initialize: function(config) {
Panel.superclass.initialize.call(this, config);
this.element = $(config.element).eq(0);
},
_onChangeColor: function(val) {
console.log('color change');//不会进入这里,除非删除initialize方法
}
});
new Panel().set(‘color’,'#eee');//我测试用的
exports.Panel = Panel;
});
目前 base及其子类 遍历继承链并构建默认atts的时机是在 类实例化 时,见代码:https://github.com/aralejs/base/blob/master/src/attribute.js#L19
个人觉得不合理且对性能有大影响:
所以希望能将 遍历继承链并构建默认atts 的时机改为 类构建 时,可以提升很大一部分性能
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
if (this.trigger.apply(this, beforeArgs) === false) return;
var ret = old.apply(this, arguments);
this.trigger('after:' + methodName, ret);
return ret;
};
this[methodName].__isAspected = true;
}
现在after
回调中没有传入被切入方法的参数,有时候被切入方法的参数对after函数有用,比如在widget
中想在元素focus
后修改元素的一些属性,现在用after
是拿不到当前target
元素的,建议after
传入被切入方法的参数,参数顺序为(被切入方法的执行结果, 被切入方法的参数1, 被切入方法的参数2,...)
。
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
if (this.trigger.apply(this, beforeArgs) === false) return;
var ret = old.apply(this, arguments);
var afterArgs = ['after:' + methodName, ret];
afterArgs = afterArgs.concat(args);
this.trigger.apply(this, afterArgs);
return ret;
};
this[methodName].__isAspected = true;
}
目前当属性值在render时的值为空字符串时,不会进入 onRenderXXX 方法。
这块处理是否恰当,要再考虑一下。
base的复制参数机制,将jquery对象拷贝到Position.VIEWPORT对象上,导致新对象依然带有_id属性。
如题,由于attribute
去掉了以下代码:
var EVENT_PATTERN = /^(on|before|after)([A-Z].*)$/;
var EVENT_NAME_PATTERN = /^(Change)?([A-Z])(.*)/;
//......
照成validator中onItemValidate等时间失效,现在只能用下面方式绑定:
validator.on('itemValidate', handler);
是否以后就只用第二种方式绑定了?
mergeInheritedAttrs方法里面的copySpecialProps有必要写吗
//本身是有值的,至空this.attrs
var attrs = this.attrs = {};
// 因为上面至空了,这里肯定是空数组
var specialProps = this.propsInAttrs || [];
//mergeInheritedAttrs({}, subClass, []);
mergeInheritedAttrs(attrs, this, specialProps);
// 将 proto 上的特殊 properties 放到 proto.attrs 上,以便合并
//copySpecialProps([], proto.attrs, subClass);
copySpecialProps(specialProps, proto.attrs, proto);
function copySpecialProps(specialProps, receiver, supplier, isAttr2Prop) {
for (var i = 0, len = specialProps.length; i < len; i++) {
var key = specialProps[i];
console.log(key);
if (supplier.hasOwnProperty(key)) {
console.log(supplier);
receiver[key] = isAttr2Prop ? receiver.get(key) : supplier[key];
}
}
}
attribute.js里42-43行代码(initAttrs 方法中):
// Convert `on/before/afterXxx` config to event handler.
parseEventsFromAttrs(this, attrs);
这段代码的作用是做 自定义事件绑定及AOP绑定 的 语法糖 ,不过attribute.js这个文件应该更专注于attribute的处理,这段代码及相关操作放base.js里会不会 更直观
P.S. 吐槽下,这是个非常好用的语法糖,可是各个文档里的都没有介绍,如果不是认真看了源码,还真可能漏了(囧) ,望文档补全,谢谢:)
简单还原代码如下:
seajs.use('widget', function(Widget){
var t = new Widget();
t.set('parentNode', document.getElementById('show'));
t.render();
});
IE8及以下报 对象不支持“hasOwnProperty”属性或方法
原因在这:https://github.com/aralejs/base/blob/master/src/attribute.js#L97
isEqual
方法内部会最终调用到isEmptyObject
,但是没有做isPlainObject
的保护判断,所以报错( IE8及以下的原生dom没有hasOwnProperty )
举例:
......
attrs = {
item:{
name:'xxx',
products:[1,2,3]
}
}
......
this.set('item',{});
this.get('item'); // -> item:{ name:'xxx', products:[1,2,3]}
也就是说set方法会自动merge,并在没有已经存在的属性值的情况下,使用原属性值。
我现在遇到的情况需要在没有值的情况下,强制覆盖掉原属性值,也就是得到结果:item:{}。
可以提供扩展么?
目前 mergeInheritedAttrs
及 mergeUserValue
是 base 初始化过程中性能消耗最大的部分。针对这2段逻辑,想了一些优化方案。
优化这2个方法内部的 merge 方法
因为操作的都是标准的格式化后的 attr 属性,不需要做 isPlainObject
判断,这个可以省掉不少,然后因为只有 value 的类型是不定的,所以只要针对 value 做merge即可,其他(getter等)可以直接用新值覆盖就值,又可以省一笔开销。
这部分 优化效果 5% - 10% 左右
更深入的思考: 为什么每次在实例初始化的时候才去计算整条原型继承链的 attrs ?
这个思路本身就是有问题的,浪费了多少无效的时间(在一个类被多次实例化的时候特别明显)。所以,将 格式化及合并继承 attrs 的工作 在 extend 的时候完成,就可以减少掉这种浪费!
优化效果 :只是简单的改了下方式,细节还没调整,结果可以看这里:http://jsperf.com/arale-base-performance 效果很明显!!
缺点 & 改进点: 这种修复方法 hack 了 Class.create
,是因为没有别的方法在 extend 的时候做些额外的事情,这个考虑优化下 class 模块?提供下相应的处理方式。
Aspect提供的before方法callback中return false无法阻止原函数执行
假设有这种继承关系 A -> B -> C
(A为最底层),ABC同时都设置了一个叫test的attr
// A
test: {
value: {
a: 'val'
},
getter: fn1,
readOnly: true
}
// B
test: {
b: 'B!'
}
// C
test: {
value: {
'a': 'fine!'
},
setter: fn2
}
实例化之后 C 的 test 为
test: {
value: {
a: 'fine!',
b: 'B!'
},
getter: fn1,
setter: fn2,
readOnly: true
}
before方法目前还是 "只读" 的,无法阻止method本身的执行,有没有计划去升级Aspect的功能?
利用before方法来阻止method的执行的应用场景还是比较多的,目前只能人肉的去trigger('before:method')
来达到目的,但是这种做法对于method的override来说就是灾难:(
代码一:
url: {
value: '',
setter: function(url) {
// ...
},
readOnly: true
}
代码二:
url: {
value: '',
readOnly: true
}
代码一初始化会报错,代码二是 OK 的,建议readOnly初始化时候setter不报错~
example in attribute.md Expected null to be 200.
如果参数为 {value:'a'},最后获得的则为 a
Attribute.js Line 208
value = value.slice();
应为
value = slice.call(value)
另,jQuery的isPlainObject实现在IE8是有bug的,使用一个NodeList实际上它不会走到catch里
/* pig.js */
define(function(require, exports, module) {
var Base = require('base');
var Pig = Base.extend({
initialize: function(name) {
this.name = name;
},
talk: function() {
alert('我是' + this.name);
}
});
module.exports = Pig;
});
和 arale/class 的例子一样,没有突出 base 的特点。
实验性质的功能, 如果后续有类似需求,可以进一步完善.
经常会只修改某个属性,比如 count,总是要先 get 计算后再 set
var count = this.get('count');
this.set('count', count++);
尤其处理对象的时候比较麻烦,写多了有点恶心
var model = this.get('model');
model.content = model.head + model.body + model.foot;
this.set('model', model);
提供 modify 方法
this.modify('count', function(count) {
return count++;
});
this.modify('model', function(model) {
return {
content: model.head + model.body + model.foot
};
});
可能很多人都不知道这个功能,我也是最近看代码才发现的
var Test = Base.extend({
attrs: {
onFocus: spy1,
onChangeXx: spy2,
beforeShow: spy3
},
show: function() {}
});
看看这个功能是如何用的,可以将一个属性注册为事件,如
onFocus
会将函数注册到 'focus' 事件上,onChangeXx
会将函数注册到 'change:xx' 事件上。beforeShow
则是将函数注册到 'before:show' 事件上。
先从分类上说,before/after 是对方法做切面,change 监听属性的变化,on 是最普通的监听。这些都放到 attr 上会很混乱,容易造成误解。
从用户角度说,这些都可以用实例方法去实现,更加优雅,如
var t = new Test();
t.on('focus', function() {});
t.before('show', function() {});
t.on('change:xx', function() {});
所以我觉得这个功能可以去掉。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.