国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

JavaScript中雙向數(shù)據(jù)綁定詳解

2019-11-19 16:40:17
字體:
供稿:網(wǎng)友

雙向數(shù)據(jù)綁定指的是將對(duì)象屬性變化綁定到UI,或者反之。換句話說,如果我們有一個(gè)擁有name屬性的user對(duì)象,當(dāng)我們給user.name賦予一個(gè)新值是UI也會(huì)相應(yīng)的顯示新的名字。同樣的,如果UI包括了一個(gè)輸入字段用來輸入用戶名,輸入一個(gè)新的值會(huì)導(dǎo)致user對(duì)象中的那么屬性發(fā)生變化。

許多流行的客戶端JavaScript框架例如Ember.js,AngularJS以及KnockoutJS都將雙向數(shù)據(jù)綁定作為自己的頭號(hào)特性。但是這并不意味著從零開始實(shí)現(xiàn)雙向數(shù)據(jù)綁定就很困難,同樣的當(dāng)我們需要雙向數(shù)據(jù)綁定時(shí)并不是只能夠選擇這些框架其中的一個(gè)。雙向數(shù)據(jù)綁定底層的思想非常的基本,它可以被壓縮成為三個(gè)步驟:

1.我們需要一個(gè)方法來識(shí)別哪個(gè)UI元素被綁定了相應(yīng)的屬性

2.我們需要監(jiān)視屬性和UI元素的變化

3.我們需要將所有變化傳播到綁定的對(duì)象和元素

雖然實(shí)現(xiàn)的方法有很多,但是最簡單也是最有效的途徑是使用發(fā)布者-訂閱者模式。思想很簡單:我們可以使用自定義的data屬性在HTML代碼中指明綁定。所有綁定起來的JavaScript對(duì)象以及DOM元素都將“訂閱”一個(gè)發(fā)布者對(duì)象。任何時(shí)候如果JavaScript對(duì)象或者一個(gè)HTML輸入字段被偵測(cè)到發(fā)生了變化,我們將代理事件到發(fā)布者-訂閱者模式,這會(huì)反過來將變化廣播并傳播到所有綁定的對(duì)象和元素。

使用jQuery的簡單實(shí)現(xiàn)

使用jQuery來實(shí)現(xiàn)雙向數(shù)據(jù)綁定非常的直接且簡單,因?yàn)檫@個(gè)流行的庫能夠是我們輕松的訂閱和發(fā)布DOM事件,以及我們自定義的事件:

function DataBinder(object_id){ //使用一個(gè)jQuery對(duì)象作為簡單的訂閱者發(fā)布者 var pubSub = jQuery({}); //我們希望一個(gè)data元素可以在表單中指明綁定:data-bind-<object_id>="<property_name>"   var data_attr = "bind-" + object_id,   message = object_id + ":change"; //使用data-binding屬性和代理來監(jiān)聽那個(gè)元素上的變化事件 // 以便變化能夠“廣播”到所有的關(guān)聯(lián)對(duì)象  jQuery(document).on("change","[data-" + data_attr + "]",function(evt){  var input = jQuery(this);  pubSub.trigger(message, [ $input.data(data_attr),$input.val()]); }); //PubSub將變化傳播到所有的綁定元素,設(shè)置input標(biāo)簽的值或者其他標(biāo)簽的HTML內(nèi)容  pubSub.on(message,function(evt,prop_name,new_val){  jQuery("[data-" + data_attr + "=" + prop_name + "]").each(function(){  var $bound = jQuery(this);  if($bound.is("input,text area,select")){   $bound.val(new_val);  }else{   $bound.html(new_val);  }  }); }); return pubSub;}

在這個(gè)實(shí)驗(yàn)中可以按照以下代碼簡單的實(shí)現(xiàn)一個(gè)User模型:

function User(uid){ var binder = new DataBinder(uid),  user = {   atttibutes: {},   //屬性設(shè)置器使用數(shù)據(jù)綁定器PubSub來發(fā)布變化    set: function(attr_name,val){    this.attriures[attr_name] = val;    binder.trigger(uid + ":change", [attr_name, val, this]);   },   get: function(attr_name){    return this.attributes[attr_name];   },   _binder: binder  };  binder.on(uid +":change",function(vet,attr_name,new_val,initiator){   if(initiator !== user){    user.set(attr_name,new_val);   }  })}

現(xiàn)在,無論我們什么時(shí)候想把模型的屬性綁定到UI的一部分上,我們只需要在相應(yīng)的HTML元素上設(shè)置一個(gè)合適的data屬性即可。

//JavaScriptvar user = new User(123);user.set("name","Wolfgang");//html<input type="number" data-bind-123="name" /> 

input字段的值會(huì)自動(dòng)反映出user對(duì)象的name屬性,反之亦然。任務(wù)完成了!

不使用jQuery來創(chuàng)建數(shù)據(jù)雙向綁定

在入如今的大多數(shù)項(xiàng)目中,都可能已經(jīng)用到了jQuery,因此完全可以借用前面的例子。但是如果我們更進(jìn)一步,移除對(duì)jQuery的依賴會(huì)怎樣呢?事實(shí)上,這并不是太困難(尤其是當(dāng)我們限定只支持IE8以上的版本)。最終,我們需要使用原生的JavaScript來實(shí)現(xiàn)一個(gè)自定義的PubSub以及觀察DOM事件。

function DataBinder(object_id){ //創(chuàng)建一個(gè)簡單地PubSub對(duì)象  var pubSub = {  callbacks: {}.  on: function(msg,calssback){   this.callbacks[msg] = this.callbacks[msg] || [];   this.callbacks[msg].push(callback);  },  publish: function(msg){   this.callbacks[msg] = this.callbacks[msg] || [];   for(var i = 0, len = this.callbacks[msg].length; i<lenli++){    this.callbacks[msg][i].apply(this,arguments);   }  } }, data_attr = "data-bind-" + object_id, message = object_id + ":change", changeHandler = function(evt){  var target = evt.target || evt.srcElemnt, //IE8兼容   prop_name = target.getAttribute(data_attr);   if(prop_name && prop_name !== ""){    pubSub.publish(message,prop_name,target.value);   } }; //監(jiān)聽變化事件并代理到PubSub  if(document.addEventListener){  document.addEventListener("change",changeHandler,false); }else{  //IE8使用attachEvent而不是addEventListener    document.attachEvent("onchange",changeHandler); } //PubSub將變化傳播到所有綁定元素  pubSub.on(message,function(vet,prop_name,new)_val){  var elements = document.querySelectorAll("[" + data_attr + "=" + prop_name + "]"),    tah_name;  for(var i = 0,len =elements.length; i < len; i++){   tag_name = elements[i].tagName.toLowerCase();   if(tag_name === "input" || tag_name === "textarea" || tag_name === "select"){   elements[i].value = new_val;   }else{    elements[i].innerHTML = new_val;   }  } }); return pubSub;}

模型可以和勤勉你的例子保持一直,除了在設(shè)置器中調(diào)用那個(gè)jQuery的trigger方法之外,它需要通過調(diào)用一個(gè)自定義的PubSub的publish方法來實(shí)現(xiàn):

//在model的設(shè)置器中 function User(uid){//...user = {//...set: function(attr_name,val){ this.attribute[attr_name] = val; //使用“publish”方法  binder.publish(uid+ ":change", attr_name, val,this);  } } //...}  

再一次,我們使用原生的JavaScript代碼實(shí)現(xiàn)了相同的結(jié)果,而不是使用臃腫的JavaScript框架。

本文譯自easy two way data-binding in JavaScript,原文地址http://www.lucaongaro.eu/blog/2012/12/02/easy-two-way-data-binding-in-javascript/

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 康乐县| 连云港市| 临高县| 宜昌市| 托里县| 和静县| 龙里县| 富阳市| 阜阳市| 江口县| 霍邱县| 邻水| 安乡县| 鄂托克前旗| 通海县| 施甸县| 彭泽县| 昌江| 扎赉特旗| 定襄县| 咸宁市| 澎湖县| 夏津县| 张家港市| 潼南县| 津南区| 樟树市| 东明县| 宾阳县| 德昌县| 和平区| 奉贤区| 内江市| 清水河县| 曲水县| 莱阳市| 饶阳县| 灵武市| 册亨县| 交口县| 洪洞县|