最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue數(shù)據(jù)代理的實(shí)現(xiàn)流程逐步講解

 更新時(shí)間:2023年01月06日 16:03:06   作者:BraveWangDev  
通過一個(gè)對(duì)象代理對(duì)另一個(gè)對(duì)象中的屬性的操作(讀/寫),就是數(shù)據(jù)代理。要搞懂Vue數(shù)據(jù)代理這個(gè)概念,那我們就要從Object.defineProperty()入手,Object.defineProperty()是Vue中比較底層的一個(gè)方法,在數(shù)據(jù)劫持,數(shù)據(jù)代理以及計(jì)算屬性等地方都或多或少的用到了本函數(shù)

一,前言

上篇,主要介紹了 Vue 數(shù)據(jù)初始化流程中,數(shù)組類型的數(shù)據(jù)劫持是如何實(shí)現(xiàn)的,核心思路如下:

出于對(duì)性能的考慮,Vue 沒有對(duì)數(shù)組采用 Object.defineProperty 進(jìn)行遞歸劫持,而是對(duì)能夠?qū)е略瓟?shù)組變化的 7 個(gè)方法進(jìn)行了攔截和重寫,實(shí)現(xiàn)了對(duì)數(shù)組的數(shù)據(jù)劫持

至此,已經(jīng)完成了對(duì)響應(yīng)式數(shù)據(jù)(對(duì)象和數(shù)組)的劫持(深層劫持)操作

本篇,繼續(xù)介紹 Vue 數(shù)據(jù)初始化流程中, Vue 實(shí)例上數(shù)據(jù)代理的實(shí)現(xiàn)

二,數(shù)據(jù)代理的實(shí)現(xiàn)

1,Vue 是如何操作數(shù)據(jù)的

在 Vue 中,是可以在外部直接通過 vm 實(shí)例進(jìn)行數(shù)據(jù)訪問和操作:

let vm = new Vue({
  el: '#app',
  data() {
    return { message: 'Hello Vue', obj: { key: "val" }, arr:[1,2,3]}
  }
});
console.log(vm.message)
console.log(vm.arr.push(4))

拋出問題:vm.message 等價(jià)于 $options.data.message,是如何實(shí)現(xiàn)的?

2,當(dāng)前是如何操作數(shù)據(jù)的

當(dāng)前代碼,外部的 vm 實(shí)例只能拿到 vm. o p t i o n s ,拿到 d a t a 需要 v m . options,拿到 data 需要 vm. options,拿到data需要vm.options.data

// src/state.js#initData
function initData(vm) {
    let data = vm.$options.data;
    data = isFunction(data) ? data.call(vm) : data;
    observe(data);
    data.message
    data.arr.push(4); 
}

要想實(shí)現(xiàn) vm.message 和 $options.data.message 等效

相當(dāng)于將 vm 實(shí)例操作代理到 $options.data 上,即實(shí)現(xiàn)數(shù)據(jù)代理

3,數(shù)據(jù)代理的思路

為了讓外部的 vm 實(shí)例能夠拿到觀測后的 data,將處理后的 data 直接掛載到 vm 上

// src/state.js#initData
function initData(vm) {
    let data = vm.$options.data;
    data = vm._data = isFunction(data) ? data.call(vm) : data;
    observe(data);
}

這樣,vm 實(shí)例就能夠在外部通過 vm._data.message 獲取到 data.message

接下來,再做一次代理,將 vm 實(shí)例操作(vm.message),代理到 vm._data 上即可

4,數(shù)據(jù)代理的實(shí)現(xiàn)

通過 Object.defineProperty 對(duì) _data 中的數(shù)據(jù)操作進(jìn)行劫持

即:vm.message 在 vm 實(shí)例上取值時(shí),將它代理到 vm._data 上取值

// src/state.js#initData
function initData(vm) {
    let data = vm.$options.data;
    data = vm._data = isFunction(data) ? data.call(vm) : data;
    observe(data);
    // 當(dāng) vm.message 在 vm 實(shí)例上取值時(shí),將它代理到vm._data上去取
    for(let key in data){
        Proxy(vm, key, '_data')
    }
}
// src/state.js#Proxy
/**
 * 代理方法
 *  當(dāng)取 vm.key 時(shí),將它代理到 vm._data上去取
 * @param {*} vm        vm 實(shí)例
 * @param {*} key       屬性名
 * @param {*} source    代理目標(biāo),這里是vm._data
 */
function Proxy(vm, key, source) {
    Object.defineProperty(vm, key, {
        get(){
            return vm[source][key]
        },
        set(newValue){
            vm[source][key] = newValue;
        }
    })
}

5,數(shù)據(jù)代理的測試

let vm = new Vue({
  el: '#app',
  data() {
    return { message: 'Hello Vue', obj: { key: "val" }, arr:[1,2,3]}
  }
});
console.log(vm)
console.log(vm.message)

觀察打印結(jié)果:

獲取 vm 實(shí)例時(shí),會(huì)通過 get 方法將 _data 全部屬性打印出來

當(dāng)前 vm 實(shí)例上,包含 data 全部屬性及對(duì)應(yīng)的 get、set 方法

這樣,就實(shí)現(xiàn)了數(shù)據(jù)代理:

當(dāng)從 vm 實(shí)例取值時(shí),就會(huì)被代理到 vm._data 取值

三,結(jié)尾

本篇主要介紹了 Vue 數(shù)據(jù)初始化流程中,Vue 實(shí)例上數(shù)據(jù)代理的實(shí)現(xiàn),核心思路如下:

  • 將 data 暴露在 vm._data 實(shí)例屬性上
  • 利用 Object.defineProperty 將 vm.xxx 操作代理到 vm._data 上

到此這篇關(guān)于Vue數(shù)據(jù)代理的實(shí)現(xiàn)流程逐步講解的文章就介紹到這了,更多相關(guān)Vue數(shù)據(jù)代理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

宁都县| 齐河县| 临西县| 呼伦贝尔市| 申扎县| 商水县| 合江县| 东山县| 黄山市| 内黄县| 西充县| 南汇区| 乌鲁木齐市| 伊吾县| 长顺县| 仲巴县| 铁岭县| 射阳县| 双鸭山市| 松滋市| 阳西县| 大渡口区| 澜沧| 特克斯县| 建昌县| 平泉县| 迁西县| 安溪县| 仪征市| 虎林市| 酉阳| 奉节县| 滦南县| 平武县| 邹平县| 鸡东县| 北安市| 视频| 东安县| 嘉兴市| 定日县|