iT邦幫忙

2023 iThome 鐵人賽

DAY 4
0
Vue.js

重新認識 Vue.js系列 第 4

重新認識 Vue.js Day04:雙向綁定的最小實現

  • 分享至 

  • xImage
  •  

安全的度過了第一個週末,先訂個小目標:順利完成七天發文吧!!

教練,我要用這個黑科技!

在剛開始懵懂無知時,連 JavaScript 都還沒摸熟的我因緣巧合之下接觸到了 Vue2,在那時可以說是發現了滿滿黑科技的感覺,遠比第一次碰到 jQuery 還要震撼,立刻就拋棄了新買三天的犀牛書投向了 Vue2 的懷抱然後後面還是還債了,到了三年後被其他前輩洗臉才發現,只會套用好像真的有局限性,因此,這次的主題就這樣誕生啦

Object.defineProPerty

讓我們隆重歡迎今天的主角,雙向綁定的最佳功臣,屬性描述器!!
在 ES5 後,Javascript 允許使用者調整屬性的描述器,我們最熟悉的 value 即為其中一個,總共有六個分別是

  1. writable:表示屬性是否可以修改,默認 false
  2. configurable:表示屬性是否可以被刪除或是修改屬性描述,默認 false
  3. enumerable:表示屬性是否可以被枚舉(循環類的函式)訪問,默認 false
  4. value:屬性值
  5. get:一個函數,用於獲取屬性的值,需要回傳一個值,當設置此描述時會忽略 writable 以及 value
  6. set:一個函數,,用於設定屬性的值,會攜帶一個設定的值,當設置此描述時會忽略 writable 以及 value

好了,現在我們對於 defineProPerty 有個基礎的認識了,那我們來稍微做一下當資料更新後的視圖更新吧
首先,我們先宣告一個函數當作 Vue 的實體,在這個時候同時會進行數據的屬性綁定

function Vue(options){
    this._data = options.data();
    definePropertys(this);
};

接下來,我們要將被接管的 DOM 提供給 Vue,我們會在 Vue 中設定一個屬性來做這件事情

Vue.prototype.$mount = function(el){
    this.$el = document.querySelector(el);
    this.$el.innerHTML = JSON.stringify(this._data);
    return this
};

暫時不考慮樣板,直接將 data 給渲染出來不然後面就沒東西寫了
接下來,我們就可以宣告一個 Vue 實體出來囉,當然,此時的數據是完全沒有設定過的

let vm = new Vue({
    data(){
        return {
            title: '標題',
            userInfo: {
                username: 'account',
                password: 'password'
            },
            pockets: {
                one: 1,
                two: 2,
                three: 3,
                other: {
                    four: 4
                }
            },
            count: 0
        }
    }
}).$mount('#app');

接下來就是重頭戲了,將數據進行綁定,此次情況是會將物件深層的內容進行監測,因此除了綁定 data 第一層的屬性以外,我們還需要一個遞迴函式來綁定內部資料

function definePropertys(vue){
    let _data = vue._data;
    let _dataTemp = {};
    function definePropertyDeep(_data){
        Object.keys(_data).forEach( key => {
            if (_data === vue._data) {
                //進行根級資料綁定
            }
            _dataTemp[key] = _data[key];
            //進行深層資料綁定
            //若此屬性為物件,繼續遞迴內部屬性
            if(_dataTemp[key] instanceof Object) {
                definePropertyDeep(_dataTemp[key])
            }
        })
    }
    definePropertyDeep(_data);
};

這邊我們已經可以獲得 Vue.data 裡面的所有屬性了,接下來只要將資料進行綁定即可,代碼如下

//根級綁定
Object.defineProperty(vue, key, {
    set(v){
        _dataTemp[key] = v;
        console.log(`setting ${key} with ${v}`);
        vue.$el.innerHTML = JSON.stringify(vue._data);
    },
    get(){
        console.log(`getting ${key} with ${_dataTemp[key]}`)
        return _dataTemp[key]
    },
})
//深層綁定
Object.defineProperty(_data, key, {
    set(v){
        _dataTemp[key] = v;
        console.log(`setting ${key} with ${v}`);
        vue.$el.innerHTML = JSON.stringify(vue._data);
    },
    get(){
        console.log(`first getting ${key} with ${_dataTemp[key]}`)
        return _dataTemp[key]
    },
});

這樣我們的資料就成功地進行綁定囉,在這個情況當有 data 進行更新的時候將會重新渲染整個畫面,那 Vue2 內部的算法將只會渲染相關視圖,這邊就還請各位多摸摸了,我還沒看那麼深啊

今天就到此結束,感謝觀看的各位!


上一篇
重新認識 Vue.js Day03:使用 CDN 掛載 Vue2
下一篇
重新認識 Vue.js Day05:雙括號置換
系列文
重新認識 Vue.js30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言