# vue3 ref 和 reactive 函式

ed。發表於2022-07-03

vue3 ref 和 reactive 函式

前言

上一篇博文介紹 setup 函式的時候,最後出現一個問題,就是在 setup 函式中,編寫一個事件,直接去修改定義的變數,發現頁面上沒有更新成功,並且控制檯報錯,那這篇部落格就是講解遇到的這個問題應該如何處理。

ref 函式介紹

  • ref 作用就是將基礎資料轉換為響應式資料,把資料包裝成響應式的引用資料型別的資料。
  • 通過對引數返回值的 value 屬性獲取響應式的值,並且修改的時候也需要對 value 進行修改。
  • 在 vue2 當中,通過給元素新增 ref='xxx' ,然後使用 refs.xxx 的方式來獲取元素,vue3 也可以。
  • 當 ref 裡面的值發生變化的時候,檢視會自動更新資料。
  • ref 可以操作基本資料型別和複雜資料型別,建議使用 ref 操作只對基本資料型別進行操作。

ref 函式使用

使用 ref 函式很簡單,首先要在頁面引用,然後就可以直接使用了,具體怎麼使用呢,下面為了方便介紹,簡單來幾個案例。

ref 函式處理基本資料型別

首先提一個需求:頁面有一個名稱需要顯示,有一個按鈕,點選按鈕的時候修改頁面展示的這個名字。

<template>
  <div>
    <h1>ref reactive 函式</h1>
    <h1>姓名:{{name_ref}}</h1>
    <el-button type="primary" @click="btn">修改名字</el-button>
  </div>
</template>
<script>
  import { ref } from 'vue'  // 引入 ref
  export default {
    setup() {
      const name = '??.'   // 建立一個變數為 ??.
      const name_ref = ref(name)   // ref 將引數包裹轉換成響應式資料
      const btn = () => {   // 按鈕點選修改名字
        name_ref = '我是??.'   // 將名字內容改為 我是??. 
      }
      return { name_ref, btn }  // 把頁面需要使用的引數和方法丟擲去
    }
  }
</script>

編寫完上面的程式碼儲存重新整理,可以正常渲染資料,但是點選按鈕修改名字的時候,出現問題!

在這裡插入圖片描述

為什麼使用過 ref 將資料對映為響應式資料還是報錯呢?我們可以先列印一下 ref 包裹後,也就是 name_ref 這個引數,看一下他的結構。

在這裡插入圖片描述
所以說修改程式碼:

<template>
  <div>
    <h1>ref reactive 函式</h1>
    <h1>姓名:{{name_ref}}</h1>
    <el-button type="primary" @click="btn">修改名字</el-button>
  </div>
</template>
<script>
  import { ref } from 'vue'
  export default {
    setup() {
      const name = '??.'
      const name_ref = ref(name)
      console.log(name_ref)
      const btn = () => {
        name_ref.value = '我是??.'  // 對響應式資料的value進行操作
      }
      return { name_ref, btn }
    }
  }
</script>

然後在儲存程式碼重新整理頁面檢視效果。

在這裡插入圖片描述
非常棒,資料完美的修改了。

有一點需要說一下哈,就是在單檔案元件中,不必寫value,因為setup方法會自動解析,簡單的可以理解成 html 程式碼不需要額外操作 value,但是邏輯層需要。

ref 函式處理複雜資料型別

首先宣告:不建議使用 ref 函式處理複雜資料型別(陣列、物件等),用 ref 函式處理基本資料型別(數字、字串等)就可以了。

例如我們寫一個案例,建立一個個人資訊,放到物件裡面展示。

<template>
  <div>
    <h1>ref reactive 函式</h1>
    <h1>姓名:{{name_ref.name}}</h1>
    <h1>年齡:{{name_ref.age}}</h1>
  </div>
</template>
<script>
  import { ref } from 'vue'
  export default {
    setup() {
      const boy = {
        name: '??.',
        age: 10
      }
      const name_ref = ref(boy)
      console.log(name_ref)
      return { name_ref }
    }
  }
</script>

我們先看一下物件被 ref 函式包裹後的資料結構。

在這裡插入圖片描述

所以說,物件而言,我們修改也是通過 value 進行操作。

<template>
  <div>
    <h1>ref reactive 函式</h1>
    <h1>姓名:{{name_ref.name}}</h1>
    <h1>年齡:{{name_ref.age}}</h1>
    <el-button type="primary" @click="btn">修改名字</el-button>
  </div>
</template>
<script>
  import { ref } from 'vue'
  export default {
    setup() {
      const boy = {
        name: '??.',
        age: 10
      }
      const name_ref = ref(boy)
      console.log(name_ref)
      const btn = () => {
        name_ref.value.name = '我是??.'  // 對響應式資料的value進行操作
        name_ref.value.age = 11  // 對響應式資料的value進行操作
      }
      return { name_ref, btn }
    }
  }
</script>

儲存程式碼,重新整理頁面,檢視效果。

在這裡插入圖片描述
看到名稱和年齡都被成功修改了。

當然了,對於陣列的操作也是一樣的啦!

<template>
  <div>
    <h1>ref reactive 函式</h1>
    <h1>姓名:{{name_ref[0]}}</h1>
    <h1>年齡:{{name_ref[1]}}</h1>
    <el-button type="primary" @click="btn">修改名字</el-button>
  </div>
</template>
<script>
  import { ref } from 'vue'
  export default {
    setup() {
      const boy = ['??.', 10]
      const name_ref = ref(boy)
      const btn = () => {
        name_ref.value[0] = '我是??.'  // 對響應式資料的value進行操作
        name_ref.value[1] = 11  // 對響應式資料的value進行操作
      }
      return { name_ref, btn }
    }
  }
</script>

儲存檢視,一樣的效果。

在這裡插入圖片描述

ref 函式獲取單個DOM元素

和 vue2 一樣,可以使用 ref 獲取元素,用法和運算元據型別相似。

頁面上有一個標籤,點選按鈕,獲取標籤的相關資料。

<template>
  <div>
    <h1>ref reactive 函式</h1>
    <p style="color: blue;" ref="boy">我是??.</p>
    <el-button type="primary" @click="btn">獲取元素</el-button>
  </div>
</template>
<script>
  import { ref, onMounted } from 'vue'
  export default {
    setup() {
      let boy = ref();
      const btn = () => {
        console.log(boy)
        console.log(boy.value)
        console.log(boy.value.innerText)
        console.log(boy.value.style.color)
      }
      return {boy, btn }
    }
  }
</script>

重新整理檢視執行效果。

在這裡插入圖片描述

其他相關方法

isRef

判斷是否為 ref 物件。

<script>
  import { ref, isRef } from 'vue'
  export default {
    setup() {
      const a = ref('a')
      const b = 'b' 
      console.log(isRef(a))   // true
      console.log(isRef(b))   // false
    }
  }
</script>

在這裡插入圖片描述

unref

如果引數為 ref,則返回內部值,否則返回引數本身。

val = isRef(val) ? val.value : val

上邊程式碼可以看懂吧?

<script>
  import { ref, unref } from 'vue'
  export default {
    setup() {
      const temp = ref(3)
      const newTemp = unref(temp) // newTemp 確保現在是數字型別 3
      const a = unref(1) // a 確保現在是數字型別 1
      console.log(newTemp, a)
    }
  }
</script>

在這裡插入圖片描述

好了,這是 ref 函式和與其常見的相關的其他函式相關的知識點內容,到此為止吧,有其他的可以自己在研究一下。

reactive 函式介紹

上面說了 ref 函式的基本用法,接下來是 reactive 函式,它的用法與 ref 函式的用法相似,也是將資料變成響應式資料,當資料發生變化時UI也會自動更新。不同的是 ref 用於基本資料型別,而 reactive 是用於複雜資料型別,所以說,不建議用 ref 函式來處理複雜資料型別的原因就是,有 reactive 來處理複雜型別資料。

reactive 函式使用

用完了 ref 函式,那 reactive 函式就很好理解了哈。

ref 函式處理物件

還是, reactive 函式用來處理陣列或者是物件,我們還是寫一個案例,操作人的基本資訊。

我們還是先列印一下用 reactive 函式包裹後的資料結構。

<template>
  <div>
    <h1>ref reactive 函式</h1>
    <p>姓名:{{boy_reactive.name}}</p>
    <p>年齡:{{boy_reactive.age}}</p>
  </div>
</template>
<script>
  import { reactive } from 'vue'
  export default {
    setup() {
      const boy = {
        name: '我是??.',
        age: 10
      }
      const boy_reactive = reactive(boy)
      console.log(boy_reactive)
      return { boy_reactive }
    }
  }
</script>

在這裡插入圖片描述
有列印的結果我們可以看見,這時候的資料就不是被包裹在 value 下面了,所以說我們可以直接獲取到。

<template>
  <div>
    <h1>ref reactive 函式</h1>
    <p>姓名:{{boy_reactive.name}}</p>
    <p>年齡:{{boy_reactive.age}}</p>
    <el-button type="primary" @click="btn">修改資訊</el-button>
  </div>
</template>
<script>
  import { reactive } from 'vue'
  export default {
    setup() {
      const boy = {
        name: '我是??.',
        age: 10
      }
      const boy_reactive = reactive(boy)
      const btn = () => {
        boy_reactive.name = '??.'
        boy_reactive.age = 11
      }
      return { boy_reactive, btn }
    }
  }
</script>

儲存重新整理,檢視效果。

在這裡插入圖片描述

ref 函式處理陣列

處理陣列的方式和處理物件的方式是一樣一樣的。

直接上程式碼:

<template>
  <div>
    <h1>ref reactive 函式</h1>
    <p>姓名:{{boy_reactive[0]}}</p>
    <p>年齡:{{boy_reactive[1]}}</p>
    <el-button type="primary" @click="btn">修改資訊</el-button>
  </div>
</template>
<script>
  import { reactive } from 'vue'
  export default {
    setup() {
      const boy = ['我是??.', 10]
      const boy_reactive = reactive(boy)
      const btn = () => {
        boy_reactive[0] = '??.'
        boy_reactive[1] = 11
      }
      return { boy_reactive, btn }
    }
  }
</script>

在這裡插入圖片描述
我們可以看到效果是一樣的。

好了,今天內容就到這裡吧,該休息了,下篇部落格主要說一下 toRef 和 toRefs 函式的使用。

好的,就到這裡,拜了個拜!

相關文章