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

詳解Vue響應(yīng)式的部分實(shí)現(xiàn)

 更新時(shí)間:2022年12月08日 14:32:48   作者:小婉子啊  
響應(yīng)式,簡(jiǎn)單來(lái)說(shuō)當(dāng)數(shù)據(jù)發(fā)生變化時(shí),對(duì)數(shù)據(jù)有依賴的代碼會(huì)重新執(zhí)行。這篇文章主要為大家介紹了Vue中響應(yīng)式的部分實(shí)現(xiàn),感興趣的可以了解一下

什么是響應(yīng)式

簡(jiǎn)單來(lái)說(shuō)當(dāng)數(shù)據(jù)發(fā)生變化時(shí),對(duì)數(shù)據(jù)有依賴的代碼會(huì)重新執(zhí)行。

例如在Vue中,當(dāng)我們的數(shù)據(jù)發(fā)生改變,界面上對(duì)該數(shù)據(jù)的引用組件會(huì)重新渲染

組件data的數(shù)據(jù)一旦變化,立即出發(fā)視圖的更新;

computed屬性在依賴發(fā)生變化時(shí),自動(dòng)重新計(jì)算新值;提供watch監(jiān)聽(tīng)器,可以監(jiān)聽(tīng)到數(shù)據(jù)的變化

Vue2與Vue3響應(yīng)式之間的區(qū)別

  • Vue2使用ES5的defineProperty實(shí)現(xiàn)
  • Vue3使用的是ES6的propxy.(PS:這也就是為什么Vue2不支持IE7/8,而Vue3不支持IE11.)

使用Object.defineProperty監(jiān)聽(tīng)對(duì)象

該方法允許精確地添加或修改對(duì)象的屬性,并返回此對(duì)象。

Object.defineProperty()方法會(huì)在直接在一個(gè)對(duì)象上定義一個(gè)新屬性,或者修改一個(gè)對(duì)象的現(xiàn)有屬性,并返回此對(duì)象

備注:(應(yīng)當(dāng)直接在object構(gòu)造器對(duì)象上調(diào)用此方法,而不是在任意一個(gè)object類型的實(shí)例上調(diào)用)

語(yǔ)法:Object.defineProperty(obj, prop, descriptor)

  • obj:要設(shè)置屬性的對(duì)象;
  • prop:要設(shè)置的屬性名,這個(gè)屬性可以是已存在也可以是不存在的;
  • descriptor:要定義或修改的屬性描述符。該參數(shù)接收一個(gè)對(duì)象,用來(lái)對(duì)屬性進(jìn)行描述。如value(值),writable(是否可重寫),enumerable(是否可枚舉)等

枚舉時(shí)使用for...inObject.keys方法可以改變這些屬性的值,默認(rèn)情況下,使用 Object.defineProperty() 添加的屬性值是不可修改(immutable)的。

對(duì)象里目前存在的屬性描述符有兩種主要形式:數(shù)據(jù)描述符和存取描述符

  • 數(shù)據(jù)描述符:是一個(gè)具有值的屬性,該值是可寫的,也可以是不可寫的
  • 存取描述符:由getter函數(shù)和setter函數(shù)所描述的屬性

一個(gè)描述符只能是這兩者其中之一,不能同時(shí)是兩者

使用Object.defineProperty監(jiān)聽(tīng)對(duì)象

利用 Object.defineProperty 重寫 getset,將對(duì)象屬性的賦值和獲取變成函數(shù),我們可以實(shí)現(xiàn)一個(gè)簡(jiǎn)單的雙向綁定

  • get: 屬性的 getter 函數(shù),如果沒(méi)有 getter,則為 undefined。當(dāng)訪問(wèn)該屬性時(shí),會(huì)調(diào)用此函數(shù)。該函數(shù)的返回值會(huì)被用作屬性的值。默認(rèn)為 undefined。
  • set: 屬性的 setter 函數(shù),如果沒(méi)有 setter,則為 undefined。當(dāng)屬性值被修改時(shí),會(huì)調(diào)用此函數(shù)。默認(rèn)為 undefined。
//實(shí)現(xiàn)一個(gè)簡(jiǎn)單的雙向綁定
const data = {}
const name = 'xiaowanzi'
Object.defineProperty(data, 'name', {
  get: function () {
    console.log('get')
    return name
  },
  set: function (newVal) {
    console.log('set')
    name = newVal
  }
})
//測(cè)試
console.log(data.name)//get xiaowanzi
data.name = 'list'//set

如果我們想讓對(duì)象的所有屬性都具有響應(yīng)式,就需要對(duì)全部屬性進(jìn)行遍歷,實(shí)現(xiàn)getter和setter:

//實(shí)現(xiàn)Vue響應(yīng)式原理
let obj = {
  name: 'aaa',
  age: 18
}
//獲取obj對(duì)象的所有key
const keys = Object.keys(obj)//Object.keys()返回一個(gè)由一個(gè)給定對(duì)象的資深可枚舉屬性組成的數(shù)組,數(shù)組中的屬性名的排列順序和正常循環(huán)遍歷該對(duì)象時(shí)返回的順序一致
//遍歷Key數(shù)組,對(duì)obj對(duì)象的每一個(gè)屬性進(jìn)行處理
keys.forEach(key => {
  //使用value變量保存key對(duì)應(yīng)的屬性值
  let value = obj[key]
  //使用Object.defineProperty
  Object.defineProperty(obj, key, {
    get() {//當(dāng)獲取屬性時(shí),回來(lái)到這里
      console.log(`${key}屬性被獲取`)
      return value
    },
    set(newValue) {//當(dāng)修改屬性時(shí),會(huì)來(lái)到這里,并且設(shè)置的值會(huì)傳給newValue
      console.log(`${key}屬性被修改`)
      //這里不能寫成obj[key]=newValue
      //如果這樣寫相當(dāng)于又對(duì)該屬性進(jìn)行修改值,又會(huì)進(jìn)入set,就死循環(huán)了
      value = newValue
    }
  })
})
?
//現(xiàn)在我們已經(jīng)可以實(shí)現(xiàn)監(jiān)聽(tīng)obj對(duì)象的讀取與修改了
console.log(obj.name)//在打印'aaa'之前會(huì)先打印'name被獲取',也就是說(shuō)監(jiān)聽(tīng)到屬性的獲取。
obj.name = 'bbb'//打印name屬性被修改,也就是說(shuō)監(jiān)聽(tīng)到了屬性的改變
?
//實(shí)現(xiàn)Vue響應(yīng)式原理
let obj={
  name:'aaa',
  age:18
}
//獲取obj對(duì)象的所有key
const keys=object.keys(obj)//Object.keys()返回一個(gè)由一個(gè)給定對(duì)象的資深可枚舉屬性組成的數(shù)組,數(shù)組中的屬性名的排列順序和正常循環(huán)遍歷該對(duì)象時(shí)返回的順序一致
//遍歷Key數(shù)組,對(duì)obj對(duì)象的每一個(gè)屬性進(jìn)行處理
keys.forEach(key=>{
  //使用value變量保存key對(duì)應(yīng)的屬性值
  let value = obj[key]
  //使用Object.defineProperty
  Object.defineProperty(obj,key,{
      get(){//當(dāng)獲取屬性時(shí),回來(lái)到這里
        console.log(`${key}屬性被獲取`)
        return value
      },
      set(newValue){//當(dāng)修改屬性時(shí),會(huì)來(lái)到這里,并且設(shè)置的值會(huì)傳給newValue
        console.log(`${key}屬性被修改`)
        //這里不能寫成obj[key]=newValue
        //如果這樣寫相當(dāng)于又對(duì)該屬性進(jìn)行修改值,又會(huì)進(jìn)入set,就死循環(huán)了
        value=newValue
      }
  })
})
?
//現(xiàn)在我們已經(jīng)可以實(shí)現(xiàn)監(jiān)聽(tīng)obj對(duì)象的讀取與修改了
console.log(obj.name)//在打印'aaa'之前會(huì)先打印'name被獲取',也就是說(shuō)監(jiān)聽(tīng)到屬性的獲取。
obj.name='bbb'//打印name屬性被修改,也就是說(shuō)監(jiān)聽(tīng)到了屬性的改變

缺點(diǎn)

可以實(shí)現(xiàn)監(jiān)聽(tīng)對(duì)象的屬性,但是它沒(méi)有辦法做到對(duì)對(duì)象新增的屬性進(jìn)行監(jiān)聽(tīng),同時(shí)也沒(méi)有辦法做到對(duì)數(shù)據(jù)進(jìn)行監(jiān)聽(tīng)

使用ES6的Proxy實(shí)現(xiàn)監(jiān)聽(tīng)對(duì)象

該API就是用來(lái)實(shí)現(xiàn)監(jiān)聽(tīng)對(duì)象的,而且該API對(duì)數(shù)組同樣也是有效果的,在使用Proxy時(shí),通常會(huì)搭配Reflect一起使用 Proxy

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

術(shù)語(yǔ):

  • handler:包含捕捉器(trap)的占位符對(duì)象,可譯為處理器對(duì)象。
  • traps:提供屬性訪問(wèn)的方法。這類似于操作系統(tǒng)中捕獲器的概念。
  • target:被 Proxy 代理虛擬化的對(duì)象。它常被作為代理的存儲(chǔ)后端。根據(jù)目標(biāo)驗(yàn)證關(guān)于對(duì)象不可擴(kuò)展性或不可配置屬性的不變量(保持不變的語(yǔ)義)

語(yǔ)法:

const p = new Proxy(target, handler)

1.第一個(gè)參數(shù)target:要包裝的目標(biāo)對(duì)象

2.第二個(gè)參數(shù)handle:接收一個(gè)對(duì)象,內(nèi)部定義了操作目標(biāo)對(duì)象時(shí)的方法;

參數(shù):

  • target:要使用 Proxy 包裝的目標(biāo)對(duì)象(可以是任何類型的對(duì)象,包括原生數(shù)組,函數(shù),甚至另一個(gè)代理)。
  • handler:一個(gè)通常以函數(shù)作為屬性的對(duì)象,各屬性中的函數(shù)分別定義了在執(zhí)行各種操作時(shí)代理 p 的行為。

方法

Reflect

是一個(gè)內(nèi)置的對(duì)象,它提供攔截 JavaScript 操作的方法。Reflect不是一個(gè)函數(shù)對(duì)象,因此它是不可構(gòu)造的。

通過(guò)給對(duì)象設(shè)置代理,我們可以攔截對(duì)象屬性的取值/賦值操作。

舉個(gè)例子:

const student = {
  age: 23
}
const handler = {
  get(target, prop) {
    console.log("讀值:", key, value);
    target[key] = value;
    return target[prop]
  },
  set(target, key, value) {
    console.log("設(shè)置值", key, value);
    target[key] = value;
    return true
  }
}
const proxy = new Proxy(studengt, handler)
console.log(proxy.age)//23
//proxy.age=32   //32

實(shí)現(xiàn)代碼

//Proxy+Reflect
let obj = {
  name: 'aaa',
  age: 18
}
//第一個(gè)參數(shù)為要代理的對(duì)象,第二個(gè)參數(shù)位hander
const proxy = new Proxy(obj, {
  //當(dāng)訪問(wèn)第一個(gè)屬性的時(shí)候會(huì)得到getter
  //同時(shí)會(huì)傳遞三個(gè)參數(shù)
  //target要進(jìn)行代理對(duì)象,這里就是obj
  //key被訪問(wèn)的屬性
  //receiver用來(lái)綁定this
  get(target, key, receiver) {
    console.log(`${key}屬性被訪問(wèn)`)
    return Reflect.get(target, key, receiver)
  },
  //當(dāng)某一屬性修改的時(shí),回來(lái)到Setter
  // 同時(shí)會(huì)傳遞四個(gè)參數(shù)
  // target要進(jìn)行代理的對(duì)象,這里就是obj
  // 可以被訪問(wèn)的屬性
  // newValue新修改的值
  // receiver用來(lái)綁定this
  set(target, key, newValue, receiver) {
    console.log(`${key}屬性修改`)
    return Reflect.set(target, key, newValue, receiver)
  }
})
// 以上代碼執(zhí)行完,得到的就是proxy對(duì)象就是obj對(duì)象的代理
// 我們只需要修改代理對(duì)象的就可以做到修改原型對(duì)象的效果
// 而且我們對(duì)代理對(duì)象的修改使我們能夠監(jiān)聽(tīng)到的
console.log(proxy.name)
proxy.name = 'bbb'

到此這篇關(guān)于詳解Vue響應(yīng)式的部分實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Vue響應(yīng)式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring中網(wǎng)絡(luò)請(qǐng)求客戶端WebClient的使用詳解

    Spring中網(wǎng)絡(luò)請(qǐng)求客戶端WebClient的使用詳解

    作為替代,Spring 官方已在 Spring 5 中引入了 WebClient 作為非阻塞式 Reactive HTTP 客戶端,本文將通過(guò)樣例演示如何使用 WebClient,希望對(duì)大家有所幫助
    2024-04-04
  • SWT(JFace) Wizard(Eclipse插件編程必備)

    SWT(JFace) Wizard(Eclipse插件編程必備)

    SWT(JFace)小制作:Wizard(Eclipse插件編程必備)
    2009-06-06
  • Mybatis環(huán)境搭建和使用實(shí)例代碼

    Mybatis環(huán)境搭建和使用實(shí)例代碼

    MyBatis 是一款優(yōu)秀的持久層框架,它支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射。本文重點(diǎn)給大家介紹Mybatis的環(huán)境搭建和使用實(shí)例代碼,需要的朋友參考下吧
    2017-12-12
  • Java原子操作CAS原理解析

    Java原子操作CAS原理解析

    這篇文章主要介紹了Java原子操作CAS原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • Java 求解如何把二叉搜索樹轉(zhuǎn)換為累加樹

    Java 求解如何把二叉搜索樹轉(zhuǎn)換為累加樹

    這篇文章主要介紹了Java 求解把二叉搜索樹轉(zhuǎn)換為累加樹的代碼,總之需要觀察示例節(jié)點(diǎn)的規(guī)律,需要記錄上個(gè)節(jié)點(diǎn)的情況,注意引入前驅(qū)節(jié)點(diǎn)pre,具體實(shí)例代碼跟隨小編一起看看吧
    2021-11-11
  • java中靜態(tài)代碼塊與構(gòu)造方法的執(zhí)行順序判斷

    java中靜態(tài)代碼塊與構(gòu)造方法的執(zhí)行順序判斷

    對(duì)靜態(tài)代碼塊以及構(gòu)造函數(shù)的執(zhí)行先后順序,一直很迷惑,直到最近看到一段代碼,發(fā)現(xiàn)終于弄懂了,所以這篇文章主要給大家介紹了關(guān)于如何判斷java中靜態(tài)代碼塊與構(gòu)造方法的執(zhí)行順序的相關(guān)資料,需要的朋友可以參考下。
    2017-12-12
  • mybatis判斷int是否為空的時(shí)候,需要注意的3點(diǎn)

    mybatis判斷int是否為空的時(shí)候,需要注意的3點(diǎn)

    這篇文章主要介紹了mybatis判斷int是否為空的時(shí)候,需要注意的3點(diǎn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • SpringBoot中過(guò)濾器Filter+JWT令牌實(shí)現(xiàn)登錄驗(yàn)證

    SpringBoot中過(guò)濾器Filter+JWT令牌實(shí)現(xiàn)登錄驗(yàn)證

    本文主要介紹了SpringBoot中過(guò)濾器Filter+JWT令牌實(shí)現(xiàn)登錄驗(yàn)證,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-04-04
  • Mybatis-Plus實(shí)現(xiàn)只更新部分字段的數(shù)據(jù)

    Mybatis-Plus實(shí)現(xiàn)只更新部分字段的數(shù)據(jù)

    這篇文章主要介紹了Mybatis-Plus實(shí)現(xiàn)只更新部分字段的數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • JAVA中使用JSON進(jìn)行數(shù)據(jù)傳遞示例

    JAVA中使用JSON進(jìn)行數(shù)據(jù)傳遞示例

    本篇文章主要介紹了JAVA中使用JSON進(jìn)行數(shù)據(jù)傳遞示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01

最新評(píng)論

承德市| 长白| 黔西县| 彭阳县| 洱源县| 香港 | 林芝县| 沭阳县| 嵩明县| 昆明市| 永福县| 南江县| 清远市| 酒泉市| 眉山市| 峡江县| 新安县| 淄博市| 余江县| 元氏县| 哈尔滨市| 张家界市| 清丰县| 邮箱| 内江市| 德令哈市| 利川市| 满城县| 信宜市| 穆棱市| 浪卡子县| 新邵县| 顺义区| 灵山县| 元谋县| 莱州市| 永寿县| 遵义县| 金堂县| 缙云县| 淮滨县|