轻松实现javascript数据双向绑定
双向数据绑定是指当对象的属性发生变化时,同时改变相应的UI的能力,反之亦然,换句话说,如果我们有一个用户对象,对象就有一个name属性。当你设置一个新值user.name,界面会显示新的价值。同样,如果UI包含数据的用户的名称输入框,输入一个新值也会导致在用户对象的名称属性的相应变化。许多流行的Javascript框架,如ember.js,Angular.js,或knockoutjs,都是宣传的双向数据绑定为主要特征。这并不意味着它是很难实现它从无到有,也不意味着我们需要这个功能,这是我们唯一的使用这些框架的选择。事实上,基本的想法是很基本的,它可以概括为以下三点:
我们需要一种方法来确定哪个UI元素绑定到哪个属性。
我们需要监控属性和UI的变化。
我们需要传播所有绑定对象和UI元素中的更改。
虽然有很多方法可以实现这一点,一个简单而有效的方法是实现用户模式。方法很简单:我们可以使用自定义数据属性作为属性需要被束缚在HTML代码。所有Javascript对象和DOM元素结合在一起,将订阅的发布和订阅的对象。每当我们检测是否Javascript对象或HTML输入元素的变化,我们通过事件代理发布-订阅对象,然后发送和广播所有的变化发生在对象和元素的结合。
jQuery实现的一个简单示例
上面讨论的实现通过jQuery非常简单明了。作为一个流行的库,它允许我们非常简单地订阅和发布DOM事件,并且我们还可以定制一个。
函数的DataBinder(object_id){
使用jQuery对象简单 / / PubSub
VaR PubSub = jQuery({ });
我们期望一个'数据'元素指定/绑定。
表单:数据绑定在
无功data_attr =绑定+ object_id,
消息= object_id +:改变;
听变化对元素/事件与数据绑定属性和代理
到 / /然后PubSub这样的变化是广播到所有连接的对象
jQuery(文档)
输入= jQuery(此);
PubSub.trigger(消息,{ $ input.data(data_attr),input.val美元()}));
});
传播变化所有的束缚/ PubSub elemetns,设定值
输入标签或HTML内容的其他标签
PubSub.on(信息、功能(EVT,prop_name,new_val){
jQuery({数据+ data_attr +=+ prop_name +})。每个(函数(){)
绑定$ = jQuery(此);
如果($ bound.is()){
bound.val美元(new_val);
其他{ }
bound.html美元(new_val);
}
});
});
返回PubSub;
}
至于Javascript对象,下面是最小化用户数据模型实现的例子:
功能的用户(UID){
VaR粘结剂=新DataBinder(UID),
用户= {
属性:{ },
属性setter发布变更使用 / DataBinder PubSub
设置:功能(attr_name,Val){
这个属性{ attr_name } = val;
Binder.trigger(UID +:变化
},
得到:功能(attr_name){
返回此属性attr_name } {;
},
_binder:粘合剂
};
PubSub / /订阅到
Binder.on(UID +:变化
如果(启动器)!=用户){
User.set(attr_name,new_val);
}
});
返回用户;
}
现在,每当我们想将一个对象的属性绑定到UI时,我们就必须在相应的HTML元素上设置适当的数据属性。
var用户=新用户(123);
user.set(名
输入输入框的值自动转换到用户名称属性,反之亦然。完成 uff01
不需要jQuery的实现。
目前大多数的项目都是在jQuery中使用的,所以上面的例子是完全可以接受的,但是如果我们不需要完全依赖jQuery,我们应该怎么做呢嗯,事实上,这样做并不难(尤其是当我们只提供IE支持超过IE8支持)。最后,我们只是希望通过发布用户模式在DOM事件。
函数的DataBinder(object_id){
一个简单的对象 / /创建PubSub
VaR PubSub = { {
回调:{ },
函数(MSG,回调){
这个回调{味精=这个回调{ { } } } | |味精;
这个回调{味精}推(回调);
},
发布:函数(MSG){
这个回调{味精=这个回调{ { } } } | |味精
对于(var i = 0,len =这个回调{味精}。长度;我< len;i++){
这个回调{味精,我}。应用(这观点);
}
}
},
data_attr =数据绑定+ object_id,
消息= object_id +:变化
changehandler =功能(EVT){
VaR目标= evt.target evt.srcelement / IE8兼容| |。
prop_name = target.getattribute(data_attr);
如果(prop_name prop_name = ={!)
PubSub.publish(消息,prop_name,目标值);
}
};
听变化事件和代理 / PubSub
如果(文件。addEventListener){
Document.addEventListener(变化
{人}
使用attachevent代替addEventListener / / IE8
document.attachevent(变化
}
PubSub的更改传播到所有绑定 / /元素
PubSub.on(信息、功能(EVT,prop_name,new_val){
var elements = document.queryselectorall({+ data_attr +=+ prop_name +})
tag_name;
对于(var i = 0,len = elements.length;我< len;i++){
tag_name =元素{我}。tagname.tolowercase();
如果(tag_name = = = = = =输入| | tag_name文本| | tag_name = 选择){
元素{我}。值= new_val;
{人}
元素的innerHTML = new_val {我};
}
}
});
返回PubSub;
}
数据模型可以保持不变。除了在jQuery在setter调用触发的方法,我们可以用它与发布方法我们定制PubSub。
模型的设置程序:
功能的用户(UID){
…
用户{ {
…
设置:功能(attr_name,Val){
这个属性{ attr_name } = val;
发布方法使用
Binder.publish(UID +:变化
}
}
…
}
通过实例,我们又一次完成了预期的结果,通过纯Javascript是少于一百行和可维护性,希望能帮助你实现Javascript数据双向绑定。