您好,登錄后才能下訂單哦!
小編給大家分享一下js項(xiàng)目中雙向數(shù)據(jù)綁定如何實(shí)現(xiàn),希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
雙向數(shù)據(jù)綁定 指的是當(dāng)對(duì)象的屬性發(fā)生變化時(shí)能夠同時(shí)改變對(duì)應(yīng)的UI,反之亦然。換句話說,如果我們有一個(gè)user對(duì)象,這個(gè)對(duì)象有一個(gè)name屬性,無論何時(shí)你對(duì)user.name設(shè)置了一個(gè)新值,UI也會(huì)展示這個(gè)新的值。同樣的,如果UI包含一個(gè)用于數(shù)據(jù)用戶名字的輸入框,輸入一個(gè)新值也會(huì)導(dǎo)致user對(duì)象的name屬性發(fā)生相應(yīng)的改變。
許多流行的javascript框架,像Ember.js,Angular.js或者KnockoutJS都會(huì)把雙向數(shù)據(jù)綁定作為其中的主要特性來宣傳。這并不意味著從頭開始實(shí)現(xiàn)它很難,也不意味著當(dāng)我們需要這種功能的時(shí)候,使用這些框架是我們唯一的選擇。內(nèi)部的潛在思想事實(shí)上是相當(dāng)基礎(chǔ)的,實(shí)現(xiàn)它可以歸納為以下三點(diǎn):
我們需要一種方式確定哪個(gè)UI元素綁定在哪個(gè)屬性上。
我們需要監(jiān)控屬性和UI的變化
我們需要把所有綁定的對(duì)象和UI元素的變化傳播出去。
發(fā)布-訂閱模式其實(shí)是一種對(duì)象間一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)送改變時(shí),所有依賴于它的對(duì)象都將得到狀態(tài)改變的通知。
訂閱者(Subscriber)把自己想訂閱的事件注冊(cè)(Subscribe)到調(diào)度中心(Event Channel),當(dāng)發(fā)布者(Publisher)發(fā)布該事件(Publish Event)到調(diào)度中心,也就是該事件觸發(fā)時(shí),由調(diào)度中心統(tǒng)一調(diào)度(Fire Event)訂閱者注冊(cè)到調(diào)度中心的處理代碼。
html 調(diào)用 端 綁定 data-bind-phone="name"
<ul> <li class="block-phone fix bd-bottom"> <label for="J_verificationPhone" data-bind-phone="tishi"><span>手機(jī)號(hào)</span></label> <input class="fix1" id="J_verificationPhone" data-bind-phone="name" name="phone" type="text" /> <button class="right J_clickTime" type="button"> <span class="award-messages-btn2 J_messagesBtn1">獲取驗(yàn)證碼</span> <span class="award-messages-btn2 J_messagesBtn2 none"><i>60</i>s后重發(fā)</span> </button> </li> <li class="block-verification fix"> <label for="J_verificationCode"><span>驗(yàn)證碼</span></label> <input class="fix1" data-bind-code="tishi" id="J_verificationCode" data-bind-phone="name" name="verification-code" class="" type="" /> </li> </ul>
js 調(diào)用 看下面代碼注釋
/** * function verficationCallback 回調(diào)方法 * [$btn1 description] * data-bind-phone="name" * @ message {[type]} 發(fā)生變化的字段phone * @ prop_name {[type]} 字段的value name * @ target {[type]} 目標(biāo)jsdom對(duì)象; * @ targetValue {[type]} 目標(biāo)jsdom對(duì)象的value */// 監(jiān)聽回調(diào)函數(shù),函數(shù)會(huì)拿到targetvalue 的值, target js dom對(duì)象,便于對(duì)變化的字段進(jìn)行操作?。?! var User= require('../../entry/module/twoWayAudio.js'); var phone = new User('phone',verficationCallback); function verficationCallback(message,prop_name,target,targetValue){ }
引入的源代碼 twoWayAudio
function DataBinder(object_id,verficationCallback){ // 創(chuàng)建一個(gè)簡(jiǎn)單的pubSub對(duì)象 var pubSub = { callbacks: {}, on: function(msg,callback) { 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 < len; i++) { this.callbacks[msg][i].apply(this,arguments); }; } }, data_attr = "data-bind-" + object_id, message = object_id + ":change", changeHandler = function(event) { var target = event.target || event.srcElement, // IE8兼容 prop_name = target.getAttribute(data_attr); if (prop_name && prop_name !== "") { if(verficationCallback){ var targetValue = target.value; verficationCallback (message,prop_name,target,targetValue); } pubSub.publish(message,prop_name,target.value); } }; // 監(jiān)聽事件變化,并代理到pubSub if (document.addEventListener) { document.addEventListener("keyup",changeHandler,false); } else{ // IE8使用attachEvent而不是addEventListenter document.attachEvent("onkeyup",changeHandler); }; // pubSub將變化傳播到所有綁定元素 pubSub.on(message,function(event,prop_name,new_val){ var elements = document.querySelectorAll("[" + data_attr + "=" +prop_name + "]"), tag_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; } function User(uid,verficationCallback) { var binder = new DataBinder(uid,verficationCallback), user = { attribute : {}, // 屬性設(shè)置器使用數(shù)據(jù)綁定器pubSub來發(fā)布 set : function(attr_name,val) { this.attribute[attr_name] = val; binder.publish(uid + ":change",attr_name,val,this); }, get : function(attr_name) { return this.attribute[attr_name]; }, _binder : binder }; binder.on(uid + ":change",function(event,attr_name,new_val,initiator) { if (initiator !== user) { user.set(attr_name,new_val); } }); return user; } module.exports = User; // phone.set( "name", "lwl" ); // phone.set( "tishi", "提示" );
替代解決方案
上面只是在掩飾雙向數(shù)據(jù)綁定,其實(shí)這種需求可以更簡(jiǎn)單的實(shí)現(xiàn) 嘿嘿
$('.block-phone #phone')[0].oninput=function(){ console.log($(this)) }
看完了這篇文章,相信你對(duì)“js項(xiàng)目中雙向數(shù)據(jù)綁定如何實(shí)現(xiàn)”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。