每次更新/更改属性时,我都需要触发一个事件,以使 dom 元素与模型上的属性值保持同步(我使用 john resig 的简单继承http://ejohn.org/blog/simple-javascript-继承/)。这可能以跨浏览器的方式进行吗?在我看来,如果我可以包装 js 用来设置属性并使其触发事件的任何函数,它就可以工作,我只是不知道该怎么做。
4 回答
JavaScript 不使用函数来设置属性。它们只是变量,设置它们不需要任何复杂的包装器。
不过,您可以使用函数来设置属性 — 与在支持类中的私有数据的语言中使用的 getter/setter 排列方式相同。这样,您的函数可以轻松运行已注册为回调的其他函数。使用 jQuery,您甚至可以将它们作为事件处理。
$(yourObject).bind('some-event-you-made-up', function() {
// This code will run whenever some-event-you-made-up is triggered on yourObject
});
// ...
$(yourObject).trigger('some-event-you-made-up');
也许你已经用 jQuery 绑定/触发器解决了你的问题,但我想告诉你,我正在构建一个更改跟踪和(最重要的是)实体建模 Javascript 框架,名为“tent”,它解决了你暴露的问题,而不需要关于对象操作的任何特殊语法,其开源并托管在:
https://github.com/benjamine/tent
它使用 JSDoc 进行记录,并使用 js-test-driver 进行了单元测试。
您可以通过这种方式使用更改跟踪模块:
var myobject = { name: 'john', age: 34 };
// add a change handler that shows changes on alert dialogs
tent.changes.bind(myobject, function(change) {
alert('myobject property '+change.data.propertyName+' changed!');
});
myobject.name = 'charly'; // gets notified on an alert dialog
它也适用于数组更改(添加、删除)。此外,您可以使用“实体”上下文将所有检测到的更改(添加、删除、修改的项目)的更改集分组到集合中、级联添加和删除、保持反向属性同步、跟踪 1 对 1、1 对 N和 N 对 M 关系等。
对象 defineProperty/defineProperties 可以解决问题。这是一个简单的代码。我已经基于它构建了一些数据绑定框架,它可能会变得非常复杂,但是要像这样练习它:
var oScope = {
$privateScope:{},
notify:function(sPropertyPath){
console.log(sPropertyPath,"changed");
}
};
Object.defineProperties(oScope,{
myPropertyA:{
get:function(){
return oScope.$privateScope.myPropertyA
},
set:function(oValue){
oScope.$privateScope.myPropertyA = oValue;
oScope.notify("myPropertyA");
}
}
});
oScope.myPropertyA = "Some Value";
//console will log: myPropertyA changed
我遇到了类似的问题,最终为 Object.defineProperty 编写了一个重载函数,将事件处理程序添加到属性中。它还提供类型检查(js-base-types)并在内部存储其值,防止不必要的更改。
正常的defineProperty示例:
Object.defineProperty(document, "property", {
get:function(){return myProperty},
set:function(value){myProperty = value},
})
var myProperty = false;
带有 onchange 事件的属性示例:
Object.defineProperty(document, "property", {
default:false,
get:function(){},
set:function(value){},
onchange:function(event){console.info(event)}
})