ES6基本的語法(六) 實(shí)現(xiàn)雙向綁定(ES5 寫法)

什么是雙向綁定

首先來說一下單向綁定,單向綁定就是把 Model 綁定到 View,當(dāng)我們用 JS 代碼更新 Model 時(shí),View 就會(huì)自動(dòng)更新。

有單向綁定,就有雙向綁定。如果用戶更新了 View,Model 的數(shù)據(jù)也自動(dòng)被更新了,這種情況就是雙向綁定。

object.defineProperty

Object.defineProperty 是 ES5 中雙向綁定的方法,下面開始介紹它的語法


Object.defineProperty(obj, prop, descriptor);

// Object.defineProperty(對(duì)象, 屬性, 描述符)

/* descriptor 對(duì)象屬性的詳細(xì)介紹 */
/* 描述符 */

value: ""  // 屬性值 默認(rèn) ''
weitable: true // 是否可寫 默認(rèn)值 false
configurable: true //是否可配置 默認(rèn)值 false
enumerable: true // 是否可枚舉 默認(rèn)值 false


/* 存取描述符 */

set: function(){} // 屬性訪問器 進(jìn)行寫操作時(shí)調(diào)用該方法
get: function(){} // 屬性訪問器 進(jìn)行讀操作時(shí)調(diào)用該方法

描述符介紹

我們在正常聲明一個(gè)對(duì)象,都是可寫,可配置,可枚舉的。例如:


let a = {
    name:'ccc'
}

a.name = "xxx" // weitable可寫

for(let i in a){
    console.log(i) //  輸出 name 說明 enumerable 可枚舉
}

delete a.name // 返回 true configurable 可配置

使用 Object.defineProperty

var a = {

}

Object.defineProperty(a,"name",{
    value: 'ccc',
})

a.name = "xxx"; // a.name 返回的還是 ccc
delete a.name  // 返回 false
for(var i in a){
    console.log(i) //返回 undefined
}

因?yàn)槲彝ㄟ^ Object.defineProperty 設(shè)置的屬性和屬性值,后面的 weitable(寫入)、configurable(配置)、enumerable(枚舉) 都是默認(rèn)值 false,所以不可寫入,不可配置,不可枚舉的。

var a = {

}

Object.defineProperty(a,"name",{
    value: 'ccc',
    weitable: true
    configurable: true,
    enumerable: true
})

a.name = "xxx"; // a.name 返回 xxx
delete a.name  // 返回 true
for(var i in a){
    console.log(i) //返回 name
}

在設(shè)置 weitable(寫入)、configurable(配置)、enumerable(枚舉)這三個(gè)屬性為 true 之后,就可以進(jìn)行寫入、配置、枚舉操作。

存取描述符

我們下一下面的例子

var a = {

}

Object.defineProperty(a,"name",{
    // 在設(shè)置 get 和 set 之后  value weitable 這兩個(gè)屬性就不能設(shè)置了
    // 在設(shè)置 get 和 set 之后  value weitable 不能共存
    configurable: true,
    enumerable: true,
    get: function (){
        console.log('執(zhí)行g(shù)et了');
    },
    set: function(){
        console.log('執(zhí)行set了');
    }
})

a.name = "ccc";         // 輸出 執(zhí)行 set 了
console.log(a.name);    // 輸出 執(zhí)行 get 了

在上面代碼中 a.name 被賦值 ccc,被 set 方法監(jiān)聽到執(zhí)行 console.log('執(zhí)行g(shù)et了')。之后又訪問 a.name 被 set 方法監(jiān)聽到執(zhí)行 console.log('執(zhí)行set了')。


var val;
var a = {

}

Object.defineProperty(a,"name",{
    // 在設(shè)置 get 和 set 之后  value weitable 這兩個(gè)屬性就不能設(shè)置了
    // 在設(shè)置 get 和 set 之后  value weitable 不能共存
    configurable: true,
    enumerable: true,
    get: function (){
        console.log('執(zhí)行g(shù)et了');
        return val;
    },
    set: function(newVal){
      console.log('執(zhí)行set了');
      val = newVal;
      console.log(val);
    }
})

a.name = "ccc";         // 輸出 執(zhí)行 set 了 并且執(zhí)行 set 里面 console.log(val) 是 ccc;
console.log(a.name);    // 輸出 執(zhí)行 get 了 打印 a.name 是 ccc

簡單的模擬一下雙向綁定

VUE2.0 雙向數(shù)據(jù)綁定核心功能由 Observe、Compile、Watcher 三部分實(shí)現(xiàn)。其中 Observer 的部分功能由 Object.defineProperty 實(shí)現(xiàn)。(Observer 監(jiān)測數(shù)據(jù)變化進(jìn)行相應(yīng)回調(diào))。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <input type="text" id='inputDemo'/> 
        <div id="txt"></div>
    </body>
    <script>
        var data = {
            value: 'ccc',
            name:{
                nameData: "ttt"
            }
        }
        inputDemo.oninput = function(){
            data.name.nameData = this.value;
        }
        function upData (){
            txt.innerText = data.name.nameData;
        }

        upData();

        // 監(jiān)控對(duì)象的某個(gè)屬性是否發(fā)生改變
        function Observer (obj) {
            // 判斷 obj 是否存在或類型不是對(duì)象 如果是直接返回 obj
            if(!obj || typeof obj != 'object') return obj;

            // 通過 keys 拿到 obj 的屬性,之后在循環(huán)一個(gè)一個(gè)拿出來
            Object.keys(obj).forEach(function(ele){
                // 執(zhí)行 defineReactive(監(jiān)聽的對(duì)象, 監(jiān)聽對(duì)象的屬性, 屬性值)
                defineReactive(obj,ele,obj[ele]);
            })
        }
        function defineReactive (obj,ele,value) {
            // 執(zhí)行遞歸 value 里面還有沒有深層的對(duì)象
            Observer(value);
            // 開始監(jiān)聽
            Object.defineProperty(obj,ele,{
                get(){
                    console.log("執(zhí)行了get")
                    return value;
                },
                set(newVal){
                    console.log("執(zhí)行了set");
                    if(newVal == value) return
                    value = newVal;
                    upData();
                }
            });
        }
        // 調(diào)用監(jiān)聽的方法
        Observer(data);

        data.value = 'xxx';

    </script>
</html>

通過這種方式寫就可以實(shí)現(xiàn) input 和 div 實(shí)現(xiàn)一個(gè)雙向綁定。

數(shù)組雙向綁定

Object.defineProper 不支持?jǐn)?shù)組的監(jiān)聽,可以用 array.prototype 原型對(duì)象

var arr = [];
var push = Array.prototype.push
function upData () {
    console.log('數(shù)組更新了')
}

var arrFun = ["pop","shift","unshift","splice ","splice", 'push']

Object.defineProperty(Array.prototype, arrFun[5], {
    value: (function(){
        return function (){
            push.apply(arr, [].slice.call(arguments));
        }
    })()
});

arr[arrFun[5]](1,2);

Object.defineProperty 除了支持監(jiān)聽數(shù)組之外,還對(duì) Observer 之后新增的對(duì)象也不支持監(jiān)聽

var data = {
    value: 'ccc',
    name:{
        nameData: "ttt"
    }
}

// 監(jiān)控對(duì)象的某個(gè)屬性是否發(fā)生改變
function Observer (obj) {
    // ...
}
function defineReactive (obj,ele,value) {
    // ...
}
// 調(diào)用監(jiān)聽的方法
Observer(data);

data.a = 10; // Object.defineProperty 對(duì)這個(gè)屬性 不支持監(jiān)聽
// 因?yàn)樵?Observer() 之后

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文能幫你做什么? 1、了解vue的雙向數(shù)據(jù)綁定原理以及核心代碼模塊 2、緩解好奇心的同時(shí)了解如何實(shí)現(xiàn)雙向綁定 為...
    44653b6bb441閱讀 235評(píng)論 0 0
  • 1、了解vue的雙向數(shù)據(jù)綁定原理以及核心代碼模塊 2、緩解好奇心的同時(shí)了解如何實(shí)現(xiàn)雙向綁定 幾種實(shí)現(xiàn)雙向綁定的做法...
    Jony0114閱讀 777評(píng)論 0 0
  • 前言 (篇幅較長,請耐心閱讀??)幾種實(shí)現(xiàn)數(shù)據(jù)綁定的方法 發(fā)布者-訂閱者模式(backbone.js) 臟值檢測(a...
    張小明_to閱讀 249評(píng)論 0 1
  • 前言 使用vue也好有一段時(shí)間了,雖然對(duì)其雙向綁定原理也有了解個(gè)大概,但也沒好好探究下其原理實(shí)現(xiàn),所以這次特意花了...
    指尖跳動(dòng)閱讀 8,029評(píng)論 0 16
  • 久違的晴天,家長會(huì)。 家長大會(huì)開好到教室時(shí),離放學(xué)已經(jīng)沒多少時(shí)間了。班主任說已經(jīng)安排了三個(gè)家長分享經(jīng)驗(yàn)。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,818評(píng)論 16 22

友情鏈接更多精彩內(nèi)容