1. 程式人生 > >用純JS實現雙向數據綁定

用純JS實現雙向數據綁定

on() his 應用 UNC 生活 settime 思路 想法 我們

雙向數據綁定指的就是,綁定對象屬性的改變到用戶界面的變化的能力,反之亦然。

換種說法,如果我們有一個user對象和一個name屬性,一旦我們賦了一個新值給user.name,在UI上就會顯示新的姓名了。同樣地,如果UI包含了一個輸入用戶姓名的輸入框,輸入一個新值就應該會使user對象的name屬性做出相應的改變。

  1. 我們需要一個UI元素和屬性相互綁定的方法
  2. 我們需要監視屬性和UI元素的變化
  3. 我們需要讓所有綁定的對象和元素都能感知到變化

還是有很多方法能夠實現上面的想法,有一個簡單有效的方法就是使用PubSub模式。

這個思路很簡單:我們使用數據特性來為HTML代碼(UI元素)進行綁定,所有被綁定在一起的JavaScript對象和DOM元素都會訂閱一個PubSub對象。只要JavaScript對象或者一個HTML輸入元素監聽到數據的變化時,就會觸發綁定到PubSub對象上的事件,從而其他綁定的對象和元素都會做出相應的變化。

<h1>原生js雙向綁定及其應用</h1>
<div class="js-2-1section2 col-sm-10 col-xs-10">
<div><input type="text" data-bind-1="peopleName" id="text1"/>
<!--data-bind-1="peopleName" 原生js雙向綁定的格式-->
</div>
<div><input type="text" data-bind-2="killName" id="text2" />
<button class
="btn btn-primary" onclick="randomGroup()">隨機詞組</button> </div> <p data-bind-1="peopleName"></p> <p data-bind-2="killName"></p> </div>
var DBind1 = new DBind( 1 );
var DBind2 = new DBind( 2 );//前面是變量,括號裏面的是html那裏填的數字
DBind1.set( "peopleName", 第一個 );
DBind2.
set( "killName", 第二個 );//第一個是剛才html格式那裏的變量名,第二個方框是賦值 function DataBinder( object_id ) { // 創建一個簡單的pubSub對象 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 + ":input", timeIn; changeHandler = function( evt ) { var target = evt.target || evt.srcElement, // IE8兼容 prop_name = target.getAttribute( data_attr ); if ( prop_name && prop_name !== "" ) { clearTimeout(timeIn); timeIn = setTimeout(function(){ pubSub.publish( message, prop_name, target.value ); },50); } }; // 監聽事件變化,並代理到pubSub if ( document.addEventListener ) { document.addEventListener( "input", changeHandler, false ); } else { // IE8使用attachEvent而不是addEventListenter document.attachEvent( "oninput", changeHandler ); } // pubSub將變化傳播到所有綁定元素 pubSub.on( message, function( evt, 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 DBind( uid ) { var binder = new DataBinder( uid ), user = { // 屬性設置器使用數據綁定器pubSub來發布 attributes: {}, set: function( attr_name, val ) { this.attributes[ attr_name ] = val; // Use the `publish` method binder.publish( uid + ":input", attr_name, val, this ); }, get: function( attr_name ) { return this.attributes[ attr_name ]; }, _binder: binder }; // Subscribe to the PubSub binder.on( uid + ":input", function( evt, attr_name, new_val, initiator ) { if ( initiator !== user ) { user.set( attr_name, new_val ); } }); return user; }

雙向綁定應用實例

function randomGroup() {
var oGroup=[];//存放所有詞匯的詞組、
for(var i=0;i<20;i++){
oGroup[i]={};//設置數組中的每個元素都是一個對象
}
//一個一個定義他們狀態的字符串,然後在下面賦值
oGroup[0].people="降龍十八掌";
oGroup[0].killer="九陰白骨爪";
oGroup[1].people="快樂大本營";
oGroup[1].killer="天天向上";
oGroup[2].people="零花錢";
oGroup[2].killer="生活費";
oGroup[3].people="爺爺";
oGroup[3].killer="姥爺";
oGroup[4].people="同學";
oGroup[4].killer="同桌";
oGroup[5].people="小沈陽";
oGroup[5].killer="宋小寶";
oGroup[6].people="成吉思汗";
oGroup[6].killer="努爾哈赤";
oGroup[7].people="謝娜張傑";
oGroup[7].killer="鄧超孫儷";
oGroup[8].people="新年";
oGroup[8].killer="跨年";
oGroup[9].people="保安";
oGroup[9].killer="保鏢";
oGroup[10].people="眉毛";
oGroup[10].killer="胡須";
oGroup[11].people="端午節";
oGroup[11].killer="中秋節";
oGroup[12].people="摩托車";
oGroup[12].killer="電動車";
oGroup[13].people="高跟鞋";
oGroup[13].killer="增高鞋";
oGroup[14].people="漢堡包";
oGroup[14].killer="肉夾饃";
oGroup[15].people="牛奶";
oGroup[15].killer="豆漿";
oGroup[16].people="唇膏";
oGroup[16].killer="口紅";
oGroup[17].people="公交";
oGroup[17].killer="地鐵";
oGroup[18].people="結婚";
oGroup[18].killer="訂婚";
oGroup[19].people="面包";
oGroup[19].killer="蛋糕";
//詞匯出自——————誰是臥底的詞匯大全
var oGroupNum=Math.floor(Math.random()*20);//抽取一個隨機數,隨機數範圍跟上面數組的長度是一致的
oPeople=oGroup[oGroupNum].people;
okiller=oGroup[oGroupNum].killer;//隨機數的對應下標的狀態字符串賦值給這個變量。
console.log(oPeople,okiller);
DBind1.set( "peopleName", oPeople );//將上面的狀態字符串賦值給input框,。這一步將在界面中直接顯示出來
DBind2.set( "killName", okiller );
}

用純JS實現雙向數據綁定