javascript實現資料的雙向繫結(手動繫結)

大溼兄發表於2018-02-04

今天來講一下Javascript是如何實現資料的雙向繫結,因為是第一次寫文章所以是借鑑了一下別人的文章。根據別人的文章來談一些自己的理解,廢話不多說直接開始講解。

首先資料雙向繫結大家一定都不陌生(如angular,vue等),那麼它的結構大致如下

<input q-value="value" type="text" id="input">
<div q-text="value" id="el"></div>
複製程式碼

這跟vue的寫法很像這是比較老的實現方式,有點像觀察者程式設計模式,主要思路是通過在資料物件上定義get和set方法(當然還有其它方法),呼叫時手動呼叫get或set資料,改變資料後出發UI層的渲染操作;以檢視驅動資料變化的場景主要應用與input、select、textarea等元素,當UI層變化時,通過監聽dom的change,keypress,keyup等事件來出發事件改變資料層的資料。整個過程均通過函式呼叫完成。 先上一段程式碼

var elems = [document.getElementById('el'), document.getElementById('input')];
複製程式碼

整體思路是先取到標籤,然後把取到的標籤放到一個陣列裡

var data = {
    value: 'hello!'
};
複製程式碼

之後定義一個初始化的值陣列data裡面value的值為hello

var command = {
        text: function(str){
            this.innerHTML = str;
        },
        value: function(str){
            this.setAttribute('value', str);
        }
};
複製程式碼

text定義文字得內容 value輸入的內容之後通過setAttribute() 方法給輸入框新增指定的文字內容 定義完之後基礎的部分也就做好了之後是需要進行邏輯的編寫

var scan = function(){
        /**
         * 掃描帶指令的節點屬性
         */
        for(var i = 0, len = elems.length; i < len; i++){
            var elem = elems[i];
            elem.command = [];
            for(var j = 0, len1 = elem.attributes.length; j < len1; j++){
                var attr = elem.attributes[j];
                if(attr.nodeName.indexOf('q-') >= 0){
                    /**
                     * 呼叫屬性指令,這裡可以使用資料改變檢測
                     */
                    command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]);
                    elem.command.push(attr.nodeName.slice(2));
                }
            }
        }
    }
複製程式碼

首先需要迴圈節點首先定義一個空陣列elem.command = []用來存取改變的值, 之後需要迴圈獲取指定字元首次出現的位置elem.attributes.length就是這個東西然後做判斷呼叫指令,這裡可以使用資料改變檢測

 command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]);
 elem.command.push(attr.nodeName.slice(2));
複製程式碼

之後可以設定掃描執行來改變檢視的顯示

function mvSet(key, value){
       data[key] = value;
       scan();
}
複製程式碼

然後通過資料繫結監聽來實現資料的繫結效果

elems[1].addEventListener('keyup', function(e){
       mvSet('value', e.target.value);
}, false);
複製程式碼

addEventListener方法用於向指定元素新增事件控制程式碼

target可返回事件目標節點(觸發該事件的節點),如生成事件的元素、文件或視窗。

最後一步就是設定時間來更新檢視的顯示

 setTimeout(function(){
        mvSet('value', data.value)
},1000)
複製程式碼

這裡繫結了剛才上面設定的陣列的值

下面帖一下整體的程式碼

<input q-value="value" type="text" id="input">
<div q-text="value" id="el"></div>
<script>
    var elems = [document.getElementById('el'), document.getElementById('input')];

    var data = {
        value: 'hello!'
    };

    var command = {
        text: function(str){
            this.innerHTML = str;
        },
        value: function(str){
            this.setAttribute('value', str);
        }
    };

    var scan = function(){
        /**
         * 掃描帶指令的節點屬性
         */
        for(var i = 0, len = elems.length; i < len; i++){
            var elem = elems[i];
            elem.command = [];
            for(var j = 0, len1 = elem.attributes.length; j < len1; j++){
                var attr = elem.attributes[j];
                if(attr.nodeName.indexOf('q-') >= 0){
                    /**
                     * 呼叫屬性指令,這裡可以使用資料改變檢測
                     */
                    command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]);
                    elem.command.push(attr.nodeName.slice(2));
                }
            }
        }
    }

    /**
     * 設定資料後掃描
     */
    function mvSet(key, value){
        data[key] = value;
        scan();
    }
    /**
     * 資料繫結監聽
     */
    elems[1].addEventListener('keyup', function(e){
        mvSet('value', e.target.value);
    }, false);

    scan();

    /**
     * 改變資料更新檢視
     */
    setTimeout(function(){
        mvSet('value', 'fuck');
    },1000)

</script>
複製程式碼

這樣就做到了javascript的雙向資料繫結,測試了一下繫結的資料還是不能改變的只能做到檢視層的改變,之後我會進一步的研究雙向繫結資料是如何改變的原理。

參考文章轉自http://www.jb51.net/article/107917.html

如有解釋上的錯誤還望各位提出來我會一一改正

經過3天的研究成果就是這麼多因為本人是第一次發文章心裡還是有點小緊張的希望各位多多包涵,謝謝。

相關文章