91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Vue3響應式的ref與reactive怎么使用

發布時間:2023-01-14 11:09:07 來源:億速云 閱讀:134 作者:iii 欄目:編程語言

這篇文章主要講解了“Vue3響應式的ref與reactive怎么使用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Vue3響應式的ref與reactive怎么使用”吧!

ref定義基本數據類型、引用數據類型的響應式。也就是說ref(value),這個value類型可以是基本數據類型,也可以是引用數據類型,但是在js中使用時必須以屬性.value格式使用,在template中可以直接調用數據。

<template>
  <div>
    <div><button @click="changeValue">修改</button></div>
    <div>
      <p>當前strRef:{{ strRef }}</p>
      <p>當前objRef:姓名:{{ objRef.name }} 愛好:{{ objRef.hobboy }}</p>
      <p>當前arrRef:{{ arrRef }}</p>
    </div>
  </div>
</template>
<script>
import { defineComponent, ref, shallowRef } from 'vue'
export default defineComponent({
  setup () {
    const strRef = ref('sapper');// 基本數據類型
    const arrRef = ref([1, 3, 2]);// 數組類型
    const objRef = ref({  // 對象類型
      name: 'sapper',
      hobboy: ['吉他', '原神']
    })
    const changeValue = () => {
      strRef.value = '工兵';
      arrRef.value[1] = 4;
      objRef.value.hobboy[1] = '滑冰';
    }
    return {strRef,objRef,arrRef,changeValue}
  }
})
</script>

reactive定義引用類型數據的響應式,不支持基本數據類型,如果需要寫基本數據類型只能是放在對象中,也就是說reactive(value),這個value類型必須是引用類型。

<template>
  <div>
    <div><button @click="changeValue">修改</button></div>
    <div>
      <div>當前objReactive:
        <br/>
        姓名:{{ objReactive.name }}<br/> 
        愛好:{{ objReactive.hobboy }}
      </div>
      <div>當前arrReactive:{{ arrReactive }}</div>
    </div>
  </div>
</template>
<script>
import { defineComponent, reactive } from 'vue'
export default defineComponent({
  setup () {
    const arrReactive = reactive([1, 3, 2]);// 數組類型
    const objReactive = reactive({  // 對象類型
      name: 'sapper',
      hobboy: ['吉他', '原神']
    })
    const changeValue = () => {
      arrReactive[1] = 4;
      objReactive.name = '工兵';
      objReactive.hobboy[1] = '滑冰';
    }
    return {objReactive,arrReactive,changeValue}
  }
})
</script>

從上面兩個例子中我們可以看出不管什么類型數據,ref都需要以.value來調用ref定義的數據,對于引用數據類型來看,我們可以看出代碼不美觀,所以一般對于引用類型數據,都推薦使用reactive來定義對于基本數據類型,可以使用ref也可以使用reactive來定義。既然到了這里我們都了解了ref和reactive的運用區別了,那么我們繼續來一起探討一下它們的響應原理又有什么區別?

揭秘ref

從上面的例子,我們先打印看一下基本數據類型(strRef)、引用數據類型(arrRef、ObjRef)的ref內部封裝結構是什么樣的?如下三圖所示

Vue3響應式的ref與reactive怎么使用

Vue3響應式的ref與reactive怎么使用

Vue3響應式的ref與reactive怎么使用從上面圖片可以看出,不管是什么類型的數據,對于ref封裝數據都是一個RefImpl對象reference implement的簡寫,是引用實現的意思,每個RefImpl對象都有6個屬性:

  • dep:是一個Set類型的數據,用來存儲當前的ref值收集的依賴。

  • _ v _ isRef :標記位,只要被ref定義了,都會標識當前數據為一個Ref,也就是它的值標記為true。

  • _ v _ isShallow:判斷是否是shallowRef定義的數據。

    與ref不同的是,當使用shallowRef為引用類型創建響應性時,修改深層屬性,不具備響應性。只有對.value的引用時才觸發。

  • const state = shallowRef({ count: 1 })
    // 不會觸發更改
    state.value.count = 2
    // 會觸發更改
    state.value = { count: 2 }
  • _ rawValue:用于保存當前ref值對應的原始值,如果傳遞的參數是對象,它就是用于保存轉化前的原始值,否則_ value與_ rawValue相同。

  • _ value:用于保存ref當前值,如果傳遞的參數是對象,它就是用于保存經過reactive函數轉化后的值,否則_ value與_ rawValue相同。從上面例子我們可以發現,對于引用類型的數據,它的值就是一個proxy對象,這其實就是reactive封裝數據后對象(后面會說)。我們先看一下下圖,發現_ rawValue就是沒有做響應性處理的原始值,在看看_ value是一個proxy對象就是做了reactive響應處理的值。

    _ rawValue_ value就是為了區分引用類型數據是否做響應式處理。

Vue3響應式的ref與reactive怎么使用

  • value:保存的是當前的值。

既然我們清楚了ref給數據封裝了什么屬性,接下來開始探討源碼究竟給怎么給上面6個屬性進行賦值的:

  • ref函數:Vue3向開發者暴露的是ref函數,其實它就是封裝了一個createRef函數。

  • export function ref(value?: unknown) {
     return createRef(value, false)
    }
  • createRef函數:有兩個參數,一個是要做響應處理的數據,一個是判斷數據是否為shallowRef定義的數據。它主要做的事情就是判斷當前rawValue(暫時沒有做響應處理的數據)是否為ref類型數據、創建RefImpl實例對象。

  • function createRef(rawValue: unknown, shallow: boolean) {
     if (isRef(rawValue)) {
       return rawValue
     }
     return new RefImpl(rawValue, shallow)
    }
  • RefImpl類:創建RefImpl類給_ rawValue和_ value屬性賦值,判斷當前定義的ref數據是否為shallowRef定義的數據,然后獲取響應性值時對數據依賴進行收集并返回_ value,修改響應式值時修改并通知依賴更新。

    ref定義的數據為什么需要帶.value調用數據? 就是因為RefImpl類暴露給實例對象的get、set方法是value,所以在調用的時候,需要帶上。

Vue3響應式的ref與reactive怎么使用

其實,RefImpl實例關鍵就在于trackRefValue(this)triggerRefValue(this, newVal)的兩個函數的處理,我們大概也知道它們就是依賴收集、依賴更新。這里就不一一探討。

揭秘Reactive

上面也說了reactive封裝數據的用法,它只支持傳入引用類型數據(數組、對象),如果需要在reactive中使用基礎類型只能放在對象中。既然這樣我們來探討一下reactive函數究竟做了什么?

const arrReactive = reactive([1, 3, 2]);// 數組類型
const objReactive = reactive({  // 對象類型
  name: 'sapper',
  hobboy: ['吉他', '原神']
})
const changeValue = () => {
  arrReactive[1] = 4;
  objReactive.name = '工兵';
  objReactive.hobboy[1] = '滑冰';
  console.log('arrReactive',arrReactive);
  console.log('objReactive',objReactive);
}


Vue3響應式的ref與reactive怎么使用

從上圖可以看出,使用reactive封裝的數據返回的都是一個proxy對象,proxy就是代理,如把一個對象代理到另一個對象,好比如房子所有者,代理房子給二手房東銷售,二手房東就可以擁有房子銷售權利。從上圖我們可以看到Proxy對象有三個屬性:

  • [[Handler]]: 創建Proxy對象傳入的第二個參數,是對當前需要代理的目標target進行一些相關配置處理。

  • [[Target]]:需要代理的目標target,也就是被代理的目標。

  • [[IsRevoked]]:表示是否可撤銷,生成可撤銷的proxy對象用Proxy.revocable()方法。 那么Proxy對象可以做什么?我們看看下面例子:

  • const houseOwner = {home:'房源',price:1200,type:'一房一廳'};
    const proxyOwner = new Proxy(houseOwner,{
     get:function (target,key){
       console.log(`${key}屬性被訪問!`)
       return target[key];
     },
     set:function(target,key,value){
       if(target[key]===value){
         return;
       }
       target[key] = value;
       return target[key];
     },
    })
    console.log(proxyOwner);
    proxyOwner.price = 1300;// 對被代理對象的修改
    proxyOwner.remark = '采光點好!';
    console.log(proxyOwner.price);// price屬性被訪問

從這個例子,可以看出Proxy對象的第二個參數給代理目標帶上相關屬性:set方法、get方法,再回到reactive封裝的數據中,數據的Handler屬性給數據帶上了五個屬性:deletePropertygetsethasownKeys。這五個屬性怎么來的?我們一起探討一下Vue3的源碼實現:

// 源碼位置:core-main/packages/reactivity/src/reactive.ts
// Vue3中暴露給開發者的是reactive方法
export function reactive(target: object) {
  // 判斷target是否只讀,是就不做處理
  if (isReadonly(target)) {
    return target
  }
  return createReactiveObject(
    target,
    false,
    mutableHandlers,
    mutableCollectionHandlers,
    reactiveMap
  )
}


createReactiveObject函數主要為了創建Proxy實例對象,參數傳了五個屬性: target(目標數據)、isReadonly(target是否只讀)、mutableHandlers(ProxyHandler)、mutableCollectionHandlers(ProxyHandler類型)、proxyMap(數據集合)。我們先了解一波createReactiveObject函數:

Vue3響應式的ref與reactive怎么使用

  • ReactiveFlags:響應式數據標記。

  • export const enum ReactiveFlags {
     SKIP = '__v_skip',// 標記對象不可進行代理
     IS_REACTIVE = '__v_isReactive',// 是否是Reactive封裝的
     IS_READONLY = '__v_isReadonly',// 是否只讀
     IS_SHALLOW = '__v_isShallow',// 是否是shallowRef封裝的
     RAW = '__v_raw'// 是否是proxy原始的target
    }
  • TargetType:target的數據類型。

  • const enum TargetType {
     INVALID = 0,
     COMMON = 1,// Array、Object類型
     COLLECTION = 2 // Set、Map、WaekMap、WeakSet類型
    }
  • baseHandlers:對于Array、Object類型數據,Proxy實例的第二個參數。傳入的baseHandlers就是mutableHandlers。這個函數主要是為了給Proxy對象帶上五個屬性。


    // 源碼位置:core-main/packages/reactivity/src/baseHandlers.ts
    export const mutableHandlers: ProxyHandler<object> = {
     // createGetter() 主要實現依賴收集和Reflect.set(target, key, value, receiver)
     get,
     // createSetter() 主要實現通知依賴更新和Reflect.get(target, key, receiver)
     set,
     // deleteProperty() 主要是刪除target的指定key的屬性Reflect.deleteProperty(target, key)
     deleteProperty,
     // has() 主要是判斷target是否存在指定key的屬性,Reflect.has(target, key)
     has,
     // ownKeys() 主要是獲取target的key數組,Reflect.ownKeys(target)
     ownKeys
    }
  • collectionHandlers:對于Set、Map、WaekMap、WeakSet類型數據,Proxy實例的第二個參數。傳入的baseHandlers就是mutableCollectionHandlers。mutableCollectionHandlers主要是對 set、map、weakSet、weakMap 四種類型的對象進行劫持。

  • // 源碼位置:core-main/packages/reactivity/src/mutableCollectionHandlers.ts
    export const mutableCollectionHandlers: ProxyHandler<CollectionTypes> = {
     get: /*#__PURE__*/ createInstrumentationGetter(false, false)
    }
    function createInstrumentationGetter(isReadonly: boolean, shallow: boolean) {
     const instrumentations = shallow?
       isReadonly? shallowReadonlyInstrumentations: shallowInstrumentations
       : isReadonly? readonlyInstrumentations: mutableInstrumentations

     return (target: CollectionTypes,key: string | symbol,receiver: CollectionTypes) => {
       ...
       return Reflect.get(
         hasOwn(instrumentations, key) && key in target? instrumentations:target,
         key,
         receiver
       )
     }
    }

感謝各位的閱讀,以上就是“Vue3響應式的ref與reactive怎么使用”的內容了,經過本文的學習后,相信大家對Vue3響應式的ref與reactive怎么使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

汝城县| 青冈县| 长春市| 和平县| 永善县| 玉屏| 榆中县| 莲花县| 惠州市| 栾川县| 哈尔滨市| 南涧| 塔河县| 天津市| 南城县| 九台市| 万载县| 桂林市| 沙雅县| 慈溪市| 苍山县| 泸西县| 达孜县| 阳泉市| 绍兴县| 汤原县| 来凤县| 济南市| 济源市| 抚州市| 阿巴嘎旗| 辽源市| 朝阳县| 社会| 周口市| 嘉荫县| 海原县| 遂宁市| 苏尼特右旗| 莫力| 开封县|