欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

Vue3中reactive和ref的區(qū)別有哪些

這篇文章主要講解了“Vue3中reactive和ref的區(qū)別有哪些”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Vue3中reactive和ref的區(qū)別有哪些”吧!

成都網(wǎng)絡(luò)公司-成都網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)公司十余年經(jīng)驗(yàn)成就非凡,專(zhuān)業(yè)從事成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì),成都網(wǎng)頁(yè)設(shè)計(jì),成都網(wǎng)頁(yè)制作,軟文發(fā)布平臺(tái),一元廣告等。十余年來(lái)已成功提供全面的成都網(wǎng)站建設(shè)方案,打造行業(yè)特色的成都網(wǎng)站建設(shè)案例,建站熱線:13518219792,我們期待您的來(lái)電!

vue2的響應(yīng)式是通過(guò)Object.defineProperty方法,劫持對(duì)象的gettersetter,在getter中收集依賴(lài),在setter中觸發(fā)依賴(lài),但是這種方式存在一些缺點(diǎn):

  • 由于是遍歷遞歸監(jiān)聽(tīng)屬性,當(dāng)屬性過(guò)多或嵌套層級(jí)過(guò)深時(shí)會(huì)影響性能

  • 無(wú)法監(jiān)聽(tīng)對(duì)象新增的屬性和刪除屬性,只能監(jiān)聽(tīng)對(duì)象本身存在的屬性,所以設(shè)計(jì)了$set$delete

  • 如果監(jiān)聽(tīng)數(shù)組的話,無(wú)法監(jiān)聽(tīng)數(shù)組元素的增減,只能監(jiān)聽(tīng)通過(guò)下標(biāo)可以訪問(wèn)到的數(shù)組中已有的屬性,由于使用Object.defineProperty遍歷監(jiān)聽(tīng)數(shù)組原有元素過(guò)于消耗性能,vue放棄使用Object.defineProperty監(jiān)聽(tīng)數(shù)組,而采用了重寫(xiě)數(shù)組原型方法的方式來(lái)監(jiān)聽(tīng)對(duì)數(shù)組數(shù)據(jù)的操作,并用$setsplice 方法來(lái)更新數(shù)組,$setsplice會(huì)調(diào)用重寫(xiě)后的數(shù)組方法。

vue3響應(yīng)式的實(shí)現(xiàn)

Proxy對(duì)象

針對(duì)Object.defineProperty的弊病, 在 ES6 中引入了一個(gè)新的對(duì)象——Proxy(對(duì)象代理)

Proxy 對(duì)象:

用于創(chuàng)建一個(gè)對(duì)象的代理,主要用于改變對(duì)象的某些默認(rèn)行為,Proxy 可以理解成,在目標(biāo)對(duì)象之前架設(shè)一層“攔截”,外界對(duì)該對(duì)象的訪問(wèn),都必須先通過(guò)這層攔截,因此提供了一種機(jī)制,可以對(duì)外界的訪問(wèn)進(jìn)行過(guò)濾和改寫(xiě)?;菊Z(yǔ)法如下:

/*
 * target: 目標(biāo)對(duì)象
 * handler: 配置對(duì)象,用來(lái)定義攔截的行為
 * proxy: Proxy構(gòu)造器的實(shí)例
 */
 var proxy = new Proxy(target,handler)

攔截get,取值操作

var proxy = new Proxy({}, {
  get: function(target, propKey) {
    return 35;
  }
});

proxy.time // 35
proxy.name // 35
proxy.title // 35

可以攔截的操作有:

函數(shù)操作
get讀取一個(gè)值
set寫(xiě)入一個(gè)值
hasin操作符
deletePropertyObject.getPrototypeOf()
getPrototypeOfObject.getPrototypeOf()
setPrototypeOfObject.setPrototypeOf()
isExtensibleObject.isExtensible()
preventExtensionsObject.preventExtensions()
getOwnPropertyDescriptorObject.getOwnPropertyDescriptor()
definePropertyObject.defineProperty
ownKeysObject.keys() Object.getOwnPropertyNames()和Object.getOwnPropertySymbols()
apply調(diào)用一個(gè)函數(shù)
constructnew一個(gè)函數(shù)

那么使用Proxy可以解決Vue2中的哪些問(wèn)題,總結(jié)一下:

  • Proxy是對(duì)整個(gè)對(duì)象的代理,而Object.defineProperty只能代理某個(gè)屬性。

  • 對(duì)象上新增屬性,Proxy可以監(jiān)聽(tīng)到,Object.defineProperty不能。

  • 數(shù)組新增修改,Proxy可以監(jiān)聽(tīng)到,Object.defineProperty不能。

  • 若對(duì)象內(nèi)部屬性要全部遞歸代理,Proxy可以只在調(diào)用的時(shí)候遞歸,而Object.definePropery需要一次完成所有遞歸,Proxy相對(duì)更靈活,提高性能。

遞歸代理

var target = {
  a:1,
  b:{
    c:2,
    d:{e:3}
  }
}
var handler = {
  get:function(target, prop, receiver){
    console.log('觸發(fā)get:',prop)
    return Reflect.get(target,prop)
  },
  set:function(target,key,value,receiver){
    console.log('觸發(fā)set:',key,value)
    return Reflect.set(target,key,value,receiver)
  }
}
var proxy = new Proxy(target,handler)
 
proxy.b.d.e = 4 
// 輸出  觸發(fā)get:b , 由此可見(jiàn)Proxy僅代理了對(duì)象外層屬性。

以上寫(xiě)法只代理了對(duì)象的外層屬性,所以要想深層代理整個(gè)對(duì)象的所有屬性,需要進(jìn)行遞歸處理:

var target = {
  a:1,
  b:{
    c:2,
    d:{e:3}
  },
  f: {z: 3}
}
var handler = {
  get:function(target, prop, receiver){
    var val = Reflect.get(target,prop)
    console.log('觸發(fā)get:',prop)
    if(val !== null && typeof val==='object') {
        return new Proxy(val,handler) // 代理內(nèi)層屬性
    }
    return Reflect.get(target,prop)
  },
  set:function(target,key,value,receiver){
    console.log('觸發(fā)set:',key,value)
    return Reflect.set(target,key,value,receiver)
  }
}
var proxy = new Proxy(target,handler)
 
proxy.b.d.e = 4 
// 輸出  觸發(fā)get b,get d, get e

從遞歸代理可以看出,如果要代理對(duì)象的內(nèi)部屬性,Proxy可以只在屬性被調(diào)用時(shí)去設(shè)置代理(惰性),訪問(wèn)了e,就僅遞歸代理b下面的屬性,不會(huì)額外代理其他沒(méi)有用到的深層屬性,如z。

關(guān)于 Reflect 的作用和意義

  • 規(guī)范語(yǔ)言?xún)?nèi)部方法的所屬對(duì)象,不全都堆放在Object對(duì)象或Function等對(duì)象的原型上。如

Function.prototype.apply
Object.defineProperty

  • 修改某些Object方法的返回結(jié)果,讓其變得更合理。比如,Object.defineProperty(obj, name, desc)在無(wú)法定義屬性時(shí),會(huì)拋出一個(gè)錯(cuò)誤,而Reflect.defineProperty(obj, name, desc)則會(huì)返回false

  • Object操作都變成函數(shù)行為。某些Object操作是命令式,比如name in objdelete obj[name],而Reflect.has(obj, name)Reflect.deleteProperty(obj, name)讓它們變成了函數(shù)行為。

  • Reflect對(duì)象的方法與Proxy對(duì)象的方法一一對(duì)應(yīng),只要是Proxy對(duì)象的方法,就能在Reflect對(duì)象上找到對(duì)應(yīng)的方法。這就讓Proxy對(duì)象可以方便地調(diào)用對(duì)應(yīng)的Reflect方法,完成默認(rèn)行為,作為修改行為的基礎(chǔ)。也就是說(shuō),不管Proxy怎么修改默認(rèn)行為,你總可以在Reflect上獲取默認(rèn)行為。

vue3的reativeref

Vue3 的 reactive 和 ref 正是借助了Proxy來(lái)實(shí)現(xiàn)。

reactive

作用:創(chuàng)建原始對(duì)象的響應(yīng)式副本,即將「引用類(lèi)型」數(shù)據(jù)轉(zhuǎn)換為「響應(yīng)式」數(shù)據(jù)

參數(shù): reactive參數(shù)必須是對(duì)象或數(shù)組

reative函數(shù)實(shí)現(xiàn):

// 判斷是否為對(duì)象
const isObject = val => val !== null && typeof val === 'object';
// 判斷key是否存在
const hasOwn = (target, key) => Object.prototype.hasOwnProperty.call(target, key);

export function reactive(target) {
    // 首先先判斷是否為對(duì)象
    if (!isObject(target)) return target;

    const handler = {
        get(target, key, receiver) {
            console.log(`獲取對(duì)象屬性${key}值`)
            // 收集依賴(lài) ...
            const result = Reflect.get(target, key, receiver)
            // 深度監(jiān)聽(tīng)(惰性)
            if (isObject(result)) {
                return reactive(result);
            }
            return result;
        },

        set(target, key, value, receiver) {
            console.log(`設(shè)置對(duì)象屬性${key}值`)

            // 首先先獲取舊值
            const oldValue = Reflect.get(target, key, reactive)

            let result = Reflect.set(target, key, value, receiver);
            
            if (result && oldValue !== value) {
                // 更新操作 ...
            }
            return result
        },

        deleteProperty(target, key) {
            console.log(`刪除對(duì)象屬性${key}值`)

            // 先判斷是否有key
            const hadKey = hasOwn(target, key)
            const result = Reflect.deleteProperty(target, key)

            if (hadKey && result) {
                // 更新操作 ...
            }

            return result
        },
        
        // 其他方法
        // ...
    }
    return new Proxy(target, handler)
}

const obj = { a: { b: { c: 6 } } };
const proxy = reactive(obj);

proxy.a.b.c = 77;

// 獲取對(duì)象屬性a值
// 獲取對(duì)象屬性b值
// 設(shè)置對(duì)象屬性c值 77

至此,引用類(lèi)型的對(duì)象我們已經(jīng)可以把它轉(zhuǎn)化成響應(yīng)式對(duì)象了,Proxy對(duì)象只能代理引用類(lèi)型的對(duì)象,對(duì)于基本數(shù)據(jù)類(lèi)型如何實(shí)現(xiàn)響應(yīng)式呢?

vue的解決方法是把基本數(shù)據(jù)類(lèi)型變成一個(gè)對(duì)象:這個(gè)對(duì)象只有一個(gè)value屬性,value屬性的值就等于這個(gè)基本數(shù)據(jù)類(lèi)型的值。然后,就可以用reative方法將這個(gè)對(duì)象,變成響應(yīng)式的Proxy對(duì)象。

實(shí)際上就是: ref(0) --> reactive( { value:0 })

ref

作用:把基本類(lèi)型的數(shù)據(jù)變?yōu)轫憫?yīng)式數(shù)據(jù)。

參數(shù):

1.基本數(shù)據(jù)類(lèi)型

2.引用類(lèi)型

3.DOM的ref屬性值

ref 實(shí)現(xiàn) Vue3 源碼

export function ref(value?: unknown) {
  return createRef(value, false)
}

function createRef(rawValue: unknown, shallow: boolean) {
  if (isRef(rawValue)) {
    return rawValue
  }
  return new RefImpl(rawValue, shallow)
}

class RefImpl{
  private _value: T
  private _rawValue: T

  public dep?: Dep = undefined
  public readonly __v_isRef = true

  constructor(value: T, public readonly __v_isShallow: boolean) {
    this._rawValue = __v_isShallow ? value : toRaw(value)
    this._value = __v_isShallow ? value : toReactive(value)
  }

  get value() {
    trackRefValue(this)
    return this._value
  }

  set value(newVal) {
    const useDirectValue =
      this.__v_isShallow || isShallow(newVal) || isReadonly(newVal)
    newVal = useDirectValue ? newVal : toRaw(newVal)
    if (hasChanged(newVal, this._rawValue)) {
      this._rawValue = newVal
      this._value = useDirectValue ? newVal : toReactive(newVal)
      triggerRefValue(this, newVal)
    }
  }
}

大體思路就是,調(diào)用ref函數(shù)時(shí)會(huì)new 一個(gè)類(lèi),這個(gè)類(lèi)監(jiān)聽(tīng)了value屬性的 get 和 set ,實(shí)現(xiàn)了在get中收集依賴(lài),在set中觸發(fā)依賴(lài),而如果需要對(duì)傳入?yún)?shù)深層監(jiān)聽(tīng)的話,就會(huì)調(diào)用我們上面提到的reactive方法。

即:

ref(0); // 通過(guò)監(jiān)聽(tīng)對(duì)象(類(lèi))的value屬性實(shí)現(xiàn)響應(yīng)式
ref({a: 6}); // 調(diào)用reactive方法對(duì)對(duì)象進(jìn)行深度監(jiān)聽(tīng)

根據(jù)上面的思路我們可以自己來(lái)簡(jiǎn)單實(shí)現(xiàn)下:

// 自定義ref
function ref(target) {
  const result = { // 這里在源碼中體現(xiàn)為一個(gè)類(lèi) RefImpl
    _value: reactive(target), // target傳給reactive方法做響應(yīng)式處理,如果是對(duì)象的話就變成響應(yīng)式
    get value () {
      return this._value
    },
    set value (val) {
      this._value = val
      console.log('set value 數(shù)據(jù)已更新, 去更新界面')
    }
  }
 
  return result
}
 
// 測(cè)試
const ref = ref(9);
ref.value = 6;

const ref = ref({a: 4});
ref.value.a = 6;

ref 方法包裝的數(shù)據(jù),需要使用.value 來(lái)訪問(wèn),但在模板中不需要,Vue解析時(shí)會(huì)自動(dòng)添加。

感謝各位的閱讀,以上就是“Vue3中reactive和ref的區(qū)別有哪些”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Vue3中reactive和ref的區(qū)別有哪些這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

分享文章:Vue3中reactive和ref的區(qū)別有哪些
文章路徑:http://aaarwkj.com/article12/iicogc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、網(wǎng)站維護(hù)、響應(yīng)式網(wǎng)站電子商務(wù)、標(biāo)簽優(yōu)化、靜態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

營(yíng)銷(xiāo)型網(wǎng)站建設(shè)
日本人妻成人免费大片| 在线观看青青草原免费| 日韩国产欧美一区二区在线视频| 未满18十八禁止观看| 国产精品欧美久久久久久| 日韩中文字幕在线首页| 亚洲熟女熟妇另类中文| 色日韩在线观看视频| 偷拍偷窥女厕一区二区视频| 色噜噜色一区二区三区| 人妻少妇中文字幕在线播放| 亚洲国产精品va在线香蕉| 亚洲理论电影在线观看| 午夜两性做爰免费视频| 国产青草视频免观看视频| 欧美黄片完整版在线观看| 五月婷婷av综合激情| 日本免费精品一区二区三区四区| 亚洲特级黄色做啪啪啪| 日韩av在线免费在线观看| 极品人妻少妇精品一区二区| 熟女人妻av五十路六十路| 欧美日本在线区一区二| 国产成人亚洲精品乱码| 国产在线麻豆在拍91精品| 18禁污污网站国产| 伊人久久综在合线亚洲| 色哟哟网站在线观看入口| jk黑丝白丝国产精品| 成年人的黄色大片网站| 亚洲国产精品综合色在线| 免费又色又爽无遮挡网站| 男女视频一区二区三区在线观看| 日本 一区二区在线| 日本成人一区二区三区在线 | 国产精品一区波多野结衣| 我要看国产一级内射片| 久久麻豆精亚洲av品国产一区| 国产欧美日韩国产精品| 成人激情视频在线观看| 亚洲日本一区二区高清在线 |