亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Vue3中關于ref和reactive的區(qū)別分析

 更新時間:2023年06月28日 09:00:05   作者:狂砍2分4籃板  
這篇文章主要介紹了vue3關于ref和reactive的區(qū)別分析,文中通過示例代碼介紹的非常詳細,具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧

一、reactive

數據類型

reactive()可用于創(chuàng)造一個響應式對象,它接受一個參數,這個參數的類型是一個重點,接下來我們先看看Vue3的源碼里是怎么處理的。

function createReactiveObject(
  target: Target,
  isReadonly: boolean,
  baseHandlers: ProxyHandler<any>,
  collectionHandlers: ProxyHandler<any>,
  proxyMap: WeakMap<Target, any>
) {
  if (!isObject(target)) {
    if (__DEV__) {
      console.warn(`value cannot be made reactive: ${String(target)}`)
    }
    return target
  }
  // ...
}

Vue3主要是調用createReactiveObject函數來創(chuàng)建reactive對象,從源碼里可以看到,該函數會首先判斷reactive()傳入的參數是不是一個對象,如果不是則不做任何處理,直接返回原值,同時開發(fā)環(huán)境下會在控制臺輸出一句警告。所以嚴格上來說,reactive()并不是像有些人說的不能傳入基本類型的參數,它可以傳,只是這種數據會失去響應式。

let name = reactive('張三')
setTimeout(() => {
  name = '李四'
  console.log(name, 'name') // 李四
}, 3000)
<template>
  <h1>{{ name }}</h1>
</template>

上面模板里仍然顯示的是張三,因為name沒有響應式不會觸發(fā)視圖更新。

原始數據與響應式數據

我們可以先定義一個原始對象,再將對象傳入reactive(),此時原始對象和響應式對象會互相干擾。

let data = { name: '張三' } // 原始對象
let state = reactive(data)
setTimeout(() => {
  state.name = '李四'
  console.log(data.name) // 李四
}, 2000)

修改響應式對象state.name的值,原始對象data.name也會同步變化。

反過來也是一樣,修改data.namestate.name也會同步變化,但需要注意的是:這種情況下雖然state.name發(fā)生了改變但視圖并不會更新

let data = { name: '張三' }
let state = reactive(data)
setTimeout(() => {
  data.name = '李四'
  console.log(state.name) // 李四,但template里仍為張三
}, 2000)
</script>
<template>
  <h1>{{ state.name }}</h1>
</template>

所以如果你是通過定義一個對象再將對象傳入reactive的話,建議始終是對響應式對象進行操作而不是原始數據。

二、ref

數據類型

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

從源碼里可以知道,ref()接受一個參數,參數可以是任意類型,這也是ref與reactive的區(qū)別之一,不管是基本類型還是引用類型ref都具備響應式,另外ref要通過.value進行取值。

let name = ref('張三') // 可以是基本類型
// 也可以是引用類型
let user = ref({
  name: '張三',
  age: 18
})
console.log(name.value)
console.log(user.value)

原始數據與響應式數據

refreactive一樣,修改原始數據或響應式數據都會同步改變對方的值,且在修改原始對象時都無法觸發(fā)視圖更新。

ref也可能是一種reactive

function createRef(rawValue: unknown, shallow: boolean) {
  if (isRef(rawValue)) {
    return rawValue
  }
  return new RefImpl(rawValue, shallow)
}
class RefImpl<T> {
  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)
    }
  }
}

通過源碼可以知道,ref是通過RefImpl這個類來創(chuàng)建的,而在RefImpl內部會調用toReactive函數,如果不是基本類型的數據,會將其轉換成reactive。

可重新賦值對象

使用reactive時,對響應式對象重新賦值是會失去響應式的。

let state = reactive({ name: '張三' })
setTimeout(() => {
  state = { name: '李四'}
  console.log(state.name) // 李四,數據變更了但視圖不會更新
}, 2000)

ref則沒有這種問題。

let state = ref({ name: '張三' })
setTimeout(() => {
  state.value = { name: '李四'}
  console.log(state.value.name) // 數據變更,同時視圖也會更新
}, 2000)

使用watch監(jiān)聽ref對象需要deep

let state = ref({ name: '張三' })
setTimeout(() => {
  state.value.name = '李四'
}, 2000)
watch(state, () => {
  console.log(state.value.name)
}, { deep: true })

reactive不加deep: truewatch也會觸發(fā),而ref則需要手動加上。

小結

  • 對于響應式而言,ref支持對象類型和基本類型,而reactive只支持對象類型
  • 當ref是對象類型的時候,本質上也是一個reactive
  • 對象類型的ref和reactive,其響應式底層原理都是Proxy

以上就是Vue3中關于ref和reactive的區(qū)別分析的詳細內容,更多關于vue3 ref 和reactive的資料請關注腳本之家其它相關文章!

相關文章

最新評論