站長資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        vue2&vue3數(shù)據(jù)響應(yīng)式原理分析及手動(dòng)實(shí)現(xiàn)(實(shí)例詳解)

        本篇文章給大家?guī)砹藇ue2&vue3數(shù)據(jù)響應(yīng)式原理分析及手動(dòng)實(shí)現(xiàn)的相關(guān)知識(shí),數(shù)據(jù)響應(yīng)式視圖跟數(shù)據(jù)是自動(dòng)更新的,數(shù)據(jù)更新的時(shí)候視圖是自動(dòng)的更新的追蹤數(shù)據(jù)的變化,希望對(duì)大家有幫助。

        vue2&vue3數(shù)據(jù)響應(yīng)式原理分析及手動(dòng)實(shí)現(xiàn)(實(shí)例詳解)

        數(shù)據(jù)響應(yīng)式

        • 視圖跟數(shù)據(jù)是自動(dòng)更新的,數(shù)據(jù)更新的時(shí)候視圖是自動(dòng)的更新的
        • 追蹤數(shù)據(jù)的變化,在讀取數(shù)據(jù)或者設(shè)置數(shù)據(jù)的時(shí)候能夠做一些劫持的一些操作
        • vue2 使用defineProperty
        • vue3 改用Proxy

        使用defineProperty

        如何追蹤變化

        var obj = {}var age  Object.defineProperty(obj, 'age', {     get: function() {         consoel.log('get age ...')         return age    },     set: function(val) {         console.log('set age ...')         age = val    }})obj.age =100 //set age ...console.log(obj.age)//get age ...

        對(duì)象obj在取age屬性的時(shí)候會(huì)調(diào)用數(shù)據(jù)劫持的get方法
        在給age屬性賦值的時(shí)候會(huì)調(diào)用set方法

        那怎么使用Object.defineProperty實(shí)現(xiàn)一個(gè)數(shù)據(jù)響應(yīng)式呢

        function defineReactive(data) {   if (!data || Object.prototype.toString.call(data) !== '[object Object]')     return;   for (let key in data) {     let val = data[key];     Object.defineProperty(data, key, {       enumerable: true, //可枚舉       configurable: true, //可配置       get: function() {         track(data, key);         return val;       },       set: function() {         trigger(val, key);       },     });     if (typeof val === "object") {       defineReactive(val);     }   }}function trigger(val, key) {   console.log("sue set", val, key);}function track(val, key) {   console.log("sue set", val, key);}const data = {   name:'better',   firends:['1','2']}defineReactive(data)console.log(data.name)console.log(data.firends[1])console.log(data.firends[0])console.log(Object.prototype.toString.call(data))

        這個(gè)函數(shù)defineReactve用來對(duì)Object.defineProperty進(jìn)行封裝,從函數(shù)名可以看出,起作用就是定義一個(gè)響應(yīng)式數(shù)據(jù),封裝后只需要傳遞data,key和val就行
        每當(dāng)從data中讀取key的時(shí)候觸發(fā)track函數(shù),往data的key中設(shè)置數(shù)據(jù)時(shí),set函數(shù)中的trigger函數(shù)觸發(fā)

        數(shù)組的響應(yīng)式

        我們通過Array原型上的方法來改變數(shù)組的內(nèi)容不會(huì)觸發(fā)getter和setter
        整理發(fā)現(xiàn)Array原型中可以改變數(shù)組自身內(nèi)容的方法有7個(gè),分別push pop shift unshift splice sort reverse
        vue2 改寫了這這7種方法
        實(shí)現(xiàn)方式:
        以Array.propertype為原型創(chuàng)建一個(gè)arrayMethods對(duì)象,再使用Object.setPropertypeOf(o, arryMethods)將o的__proto__指向arrayMethods

        vue2&vue3數(shù)據(jù)響應(yīng)式原理分析及手動(dòng)實(shí)現(xiàn)(實(shí)例詳解)

        如何收集依賴

        使用

        <template><p>{{name}}</p></template>

        該模板中使用數(shù)據(jù) name, 我們要觀察數(shù)據(jù), 當(dāng)數(shù)據(jù)的屬性發(fā)生變化的時(shí)候, 可以通知哪些使用的地方,
        這就是我們要先收集依賴,即把用到數(shù)據(jù)name的地方收集起來,然后等數(shù)據(jù)變化的時(shí)候,把之前收集好的依賴循環(huán)觸發(fā)一遍,總結(jié)來說就是getter中收集依賴,在setter中觸發(fā)依賴

        使用proxy

        Proxy對(duì)象用于創(chuàng)建一個(gè)對(duì)象的代理, 從而實(shí)現(xiàn)基本操作的攔截和定義(如屬性查找、賦值、枚舉、函數(shù)掉用等)

        const p = new Proxy(target, handler)
        • target

        • 要使用 Proxy 包裝的目標(biāo)對(duì)象(可以是任何類型的對(duì)象,包括原生數(shù)組,函數(shù),甚至另一個(gè)代理)。

        • handler

        • 一個(gè)通常以函數(shù)作為屬性的對(duì)象,各屬性中的函數(shù)分別定義了在執(zhí)行各種操作時(shí)代理 p 的行為。
          reflect是一個(gè)內(nèi)置對(duì)象, 他提供攔截javascript操作的方法, 這些方法和Proxy handlers相同

        Reflect.set將值分配給屬性的函數(shù)。返回一個(gè)Boolean 如果更新成功則返回true

        Reflect.get獲取對(duì)象身上某個(gè)屬性的值,類似target[name]

        如何實(shí)現(xiàn)劫持

        const dinner = {   meal:'111'}const handler = {   get(target, prop) {     console.log('get...', prop)     return Reflect.get(...arguments)   },   set(target, key, value) {     console.log('get...', prop)     console.log('set',key,value)     return Reflect.set(...arguments)   }}const proxy = new Proxy(dinner, handler)console.log(proxy.meal)console.log(proxy.meal)

        代碼中dinner 對(duì)象代理到handler上
        defineProperty區(qū)別
        defineProperty的屬性需要遍歷才能監(jiān)管所有屬性

        使用proxy可以將對(duì)象所有屬性進(jìn)行代理

        用proxy實(shí)現(xiàn)一個(gè)模擬響應(yīng)式

        function reactive(obj) {   const handler = {     get(target, prop, receiver) {       track(target, prop);       const value =  Reflect.get(...arguments);       if(typeof value === 'Object') {         reactive(value)       }else {         return value      }     },     set(target,key, value, receiver) {       trigger(target,key, value);       return Reflect.set(...arguments);     },   };   return new Proxy(obj,handler)}function track(data, key) {   console.log("sue set", data, key);}function trigger(data, key,value) {   console.log("sue set", key,':',value);}const dinner = {   name:'haochi1'}const proxy  =reactive(dinner)proxy.name proxy.list = []proxy.list.push(1)

        執(zhí)行后自動(dòng)打印

        vue2&amp;vue3數(shù)據(jù)響應(yīng)式原理分析及手動(dòng)實(shí)現(xiàn)(實(shí)例詳解)

        思考:為啥只在get中使用遞歸,set不使用呢?

        賦值也需要先get

        簡單總結(jié):

        1. vue2 (淺響應(yīng)式)
        • 遍歷data,使用defineProperty攔截所有屬性
        • 當(dāng)用戶操作視圖,會(huì)觸發(fā)set攔截器
        • set先改變當(dāng)前數(shù)據(jù), 再通知wartch, 讓watch去通知視圖更新
        • 視圖重繪, 再次從get中獲取對(duì)應(yīng)的數(shù)據(jù)
        1. vue3 (深度響應(yīng)式) :
        • 使用proxy 進(jìn)行代理;攔截data任意屬性的任意操作(13種), 包括屬性的讀寫, 屬性的添加, 屬性的刪除等等

        • 使用Reflect進(jìn)行反射; 動(dòng)態(tài)對(duì)被代理的對(duì)象的相應(yīng)屬性進(jìn)行特定的操作

        • 代理對(duì)象(proxy)的反射對(duì)象(reflect)必須相互配合才能實(shí)現(xiàn)響應(yīng)式

        兩者的不同

        Proxy能劫持整個(gè)對(duì)象,而Object.defineProperty只能劫持對(duì)象的屬性; 前者遞歸返回屬性對(duì)應(yīng)的值的代理即可實(shí)現(xiàn)響應(yīng)式,后者需要深度遍歷每個(gè)屬性,后者對(duì)數(shù)組的操作很不友好.

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
        主站蜘蛛池模板: 九九久久精品无码专区| 国产成人精品高清在线观看93| 精品无码一区二区三区亚洲桃色 | 久久精品国产亚洲一区二区三区 | 国内精品免费视频精选在线观看| 国产精品分类视频分类一区| 国产69精品久久久久9999| 国产精品夜色视频一级区 | 93精91精品国产综合久久香蕉| 国产精品成人无码久久久久久| 国产在线观看高清精品| 国产精品色视频ⅹxxx | 亚洲精品亚洲人成在线观看下载| 久久精品无码一区二区无码| 精品国产第1页| 蜜臀久久99精品久久久久久| 亚洲国产另类久久久精品黑人| 女人香蕉久久**毛片精品| 久久免费99精品国产自在现线| 无码人妻精品一区二区在线视频| 四虎国产成人永久精品免费| 久久噜噜久久久精品66| 99久久免费国产精品| 国产成人精品免费久久久久| 在线观看亚洲精品国产| 久久九九有精品国产23百花影院| 国模和精品嫩模私拍视频| 国产91精品黄网在线观看| 3级黄性日本午夜精品| 精品亚洲一区二区| 伊人久久大香线蕉精品| 精品999在线| 国产69精品久久久久777| 久久精品中文闷骚内射| 亚洲AV无码乱码精品国产| 国产精品高清2021在线| 99热精品毛片全部国产无缓冲| 97r久久精品国产99国产精| 国语自产精品视频在线区| 一本一本久久a久久综合精品蜜桃 一本一道精品欧美中文字幕 | 国产日韩久久久精品影院首页 |