vue3經常使用的API實用型

vue3.x已經發布了這麼久,相關的生態也慢慢起來了,包括vite這個新的打包工具,在vue3.0學習過程當中有一些實用性的api對比,但願能在開發中給你們作個示範,準確的使用對應的api去完成咱們的項目開發前端

生命週期的變動

要特別說明一下的就是,setup 函數代替了 beforeCreatecreated 兩個生命週期函數,所以咱們能夠認爲它的執行時間在beforeCreatecreated 之間vue

Vue2 Vue3
beforeCreate setup
created setup
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeDestory onBeforeUnmount
destoryed onUnmounted

瞭解過vue3的小夥伴兒都知道,如今使用都會用到setup函數,關於在setup函數操做數據,咱們用例子說明會好一點react

reactive

reactive 方法是用來建立一個響應式的數據對象,該API也很好地解決了Vue2經過 defineProperty 實現數據響應式的缺陷vuex

用法很簡單,只需將數據做爲參數傳入便可api

<template>
  <div id="app">
   <!-- 4. 訪問響應式數據對象中的 count  -->
   {{ state.count }}
  </div>
</template>

<script>
// 1. 從 vue 中導入 reactive 
import {reactive} from 'vue'
export default {
  name: 'App',
  setup() {
    // 2. 建立響應式的數據對象
    const state = reactive({count: 3})

    // 3. 將響應式數據對象state return 出去,供template使用
    return {state}
  }
}
</script>

ref

在介紹 setup 函數時,咱們使用了 ref 函數包裝了一個響應式的數據對象,這裏表面上看上去跟 reactive 好像功能如出一轍啊,確實差很少,由於 ref 就是經過 reactive 包裝了一個對象 ,而後是將值傳給該對象中的 value 屬性,這也就解釋了爲何每次訪問時咱們都須要加上 .value性能優化

咱們能夠簡單地把 ref(obj) 理解爲這個樣子 reactive({value: obj})app

<script>
import {ref, reactive} from 'vue'
export default {
  name: 'App',
  setup() {
   const obj = {count: 3}
   const state1 = ref(obj)
   const state2 = reactive(obj)

    console.log(state1)
    console.log(state2)
  }
  
}
</script>

image

注意: 這裏指的 .value 是在 setup 函數中訪問 ref 包裝後的對象時才須要加的,在 template 模板中訪問時是不須要的,由於在編譯時,會自動識別其是否爲 ref 包裝過的函數

那麼咱們到底該如何選擇 refreactive 呢?

建議:工具

  1. 基本類型值(StringNmuberBoolean 等)或單值對象(相似像 {count: 3} 這樣只有一個屬性值的對象)使用 ref
  2. 引用類型值(ObjectArray)使用 reactive

咱們在vue2.x中獲取元素標籤是用 ref ,vue3.x咱們要獲取元素標籤怎麼辦呢?

<template>
  <div>
    <div ref="el">div元素</div>
  </div>
</template>

<script>
import { ref, onMounted } from 'vue'
export default {
  setup() {
    // 建立一個DOM引用,名稱必須與元素的ref屬性名相同
    const el = ref(null)

    // 在掛載後才能經過 el 獲取到目標元素
    onMounted(() => {
      el.value.innerHTML = '內容被修改'
    })

    // 把建立的引用 return 出去
    return {el}
  }
}
</script>

獲取元素的操做一共分爲如下幾個步驟:性能

  1. 先給目標元素的 ref 屬性設置一個值,假設爲 el
  2. 而後在 setup 函數中調用 ref 函數,值爲 null,並賦值給變量 el,這裏要注意,該變量名必須與咱們給元素設置的 ref 屬性名相同
  3. 把對元素的引用變量 el 返回(return)出去
補充:設置的元素引用變量只有在組件掛載後才能訪問到,所以在掛載前對元素進行操做都是無效的

固然若是咱們引用的是一個組件元素,那麼得到的將是該組件的實例對象

toRef

toRef 是將某個對象中的某個值轉化爲響應式數據,其接收兩個參數,第一個參數爲 obj 對象;第二個參數爲對象中的屬性名

<script>
// 1. 導入 toRef
import {toRef} from 'vue'
export default {
    setup() {
        const obj = {count: 3}
        // 2. 將 obj 對象中屬性count的值轉化爲響應式數據
        const state = toRef(obj, 'count')
  
        // 3. 將toRef包裝過的數據對象返回供template使用
        return {state}
    }
}
</script>

上面又有個ref,又有個toRef,不是衝突了嗎?兩個有不同的功效:

<template>
    <p>{{ state1 }}</p>
    <button @click="add1">增長</button>

 <p>{{ state2 }}</p>
    <button @click="add2">增長</button>
</template>

<script>
import {ref, toRef} from 'vue'
export default {
    setup() {
        const obj = {count: 3}
        const state1 = ref(obj.count)
        const state2 = toRef(obj, 'count')

        function add1() {
            state1.value ++
            console.log('原始值:', obj);
            console.log('響應式數據對象:', state1);
        }

        function add2() {
            state2.value ++
            console.log('原始值:', obj);
            console.log('響應式數據對象:', state2);
        }

        return {state1, state2, add1, add2}
    }
}
</script>

ref 是對原數據的一個拷貝,不會影響到原始值,同時響應式數據對象值改變後會同步更新視圖
toRef 是對原數據的一個引用,會影響到原始值,可是響應式數據對象值改變後會不會更新視圖

toRefs

將傳入的對象裏全部的屬性的值都轉化爲響應式數據對象,該函數支持一個參數,即 obj 對象

<script>
// 1. 導入 toRefs
import {toRefs} from 'vue'
export default {
    setup() {
        const obj = {
          name: '前端印象',
          age: 22,
          gender: 0
        }
        // 2. 將 obj 對象中屬性count的值轉化爲響應式數據
        const state = toRefs(obj)
  
        // 3. 打印查看一下
        console.log(state)
    }
}
</script>

返回的是一個對象,對象裏包含了每個包裝事後的響應式數據對象

shallowReactive

聽這個API的名稱就知道,這是一個淺層的 reactive,難道意思就是本來的 reactive 是深層的唄,沒錯,這是一個用於性能優化的API

<script>
<template>
 <p>{{ state.a }}</p>
 <p>{{ state.first.b }}</p>
 <p>{{ state.first.second.c }}</p>
 <button @click="change1">改變1</button>
 <button @click="change2">改變2</button>
</template>
<script>
import {shallowReactive} from 'vue'
export default {
    setup() {
        const obj = {
          a: 1,
          first: {
            b: 2,
            second: {
              c: 3
            }
          }
        }
        
        const state = shallowReactive(obj)
  
        function change1() {
          state.a = 7
        }

        function change2() {
          state.first.b = 8
          state.first.second.c = 9
          console.log(state);
        }

        return {state}
    }
}
</script>

首先咱們點擊了第二個按鈕,改變了第二層的 b 和第三層的 c,雖然值發生了改變,可是視圖卻沒有進行更新;

當咱們點擊了第一個按鈕,改變了第一層的 a 時,整個視圖進行了更新;

由此可說明,shallowReactive 監聽了第一層屬性的值,一旦發生改變,則更新視圖

shallowRef

這是一個淺層的 ref,與 shallowReactive 同樣是拿來作性能優化的,配合triggerRef ,調用它就能夠立馬更新視圖,其接收一個參數 state ,即須要更新的 ref 對象

shallowReactive 是監聽對象第一層的數據變化用於驅動視圖更新,那麼 shallowRef 則是監聽 .value 的值的變化來更新視圖的

<template>
 <p>{{ state.a }}</p>
 <p>{{ state.first.b }}</p>
 <p>{{ state.first.second.c }}</p>
 <button @click="change">改變</button>
</template>

<script>
import {shallowRef, triggerRef} from 'vue'
export default {
    setup() {
        const obj = {
          a: 1,
          first: {
            b: 2,
            second: {
              c: 3
            }
          }
        }
        
        const state = shallowRef(obj)
        console.log(state);

        function change() {
          state.value.first.b = 8
          state.value.first.second.c = 9
          // 修改值後當即驅動視圖更新
          triggerRef(state)
          console.log(state);
        }

        return {state, change}
    }
}
</script>

toRaw

toRaw 方法是用於獲取 refreactive 對象的原始數據的

<script>
import {reactive, toRaw} from 'vue'
export default {
    setup() {
        const obj = {
          name: '前端印象',
          age: 22
        }

        const state = reactive(obj) 
        const raw = toRaw(state)

        console.log(obj === raw)   // true
    }
}
</script>

上述代碼就證實了 toRaw 方法從 reactive 對象中獲取到的是原始數據,所以咱們就能夠很方便的經過修改原始數據的值而不更新視圖來作一些性能優化了

注意: 補充一句,當 toRaw 方法接收的參數是 ref 對象時,須要加上 .value 才能獲取到原始數據對象

markRaw

markRaw 方法能夠將原始數據標記爲非響應式的,即便用 refreactive 將其包裝,仍沒法實現數據響應式,其接收一個參數,即原始數據,並返回被標記後的數據。即便咱們修改了值也不會更新視圖了,即沒有實現數據響應式

<template>
 <p>{{ state.name }}</p>
 <p>{{ state.age }}</p>
 <button @click="change">改變</button>
</template>

<script>
import {reactive, markRaw} from 'vue'
export default {
    setup() {
        const obj = {
          name: '前端印象',
          age: 22
        }
        // 經過markRaw標記原始數據obj, 使其數據更新再也不被追蹤
        const raw = markRaw(obj)   
        // 試圖用reactive包裝raw, 使其變成響應式數據
        const state = reactive(raw) 

        function change() {
          state.age = 90
          console.log(state);
        }

        return {state, change}
    }
}
</script>

watchEffect

watchEffect 它與 watch 的區別主要有如下幾點:

  1. 不須要手動傳入依賴
  2. 每次初始化時會執行一次回調函數來自動獲取依賴
  3. 沒法獲取到原值,只能獲得變化後的值
<script>
import {reactive, watchEffect} from 'vue'
export default {
    setup() { 
          const state = reactive({ count: 0, name: 'zs' })

          watchEffect(() => {
          console.log(state.count)
          console.log(state.name)
          /*  初始化時打印:
                  0
                  zs

            1秒後打印:
                  1
                  ls
          */
          })

          setTimeout(() => {
            state.count ++
            state.name = 'ls'
          }, 1000)
    }
}
</script>

沒有像 watch 方法同樣先給其傳入一個依賴,而是直接指定了一個回調函數

當組件初始化時,將該回調函數執行一次,自動獲取到須要檢測的數據是 state.countstate.name

根據以上特徵,咱們能夠自行選擇使用哪個監聽器

getCurrentInstance

咱們都知道在Vue2的任何一個組件中想要獲取當前組件的實例能夠經過 this 來獲得,而在Vue3中咱們大量的代碼都在 setup 函數中運行,而且在該函數中 this 指向的是undefined,那麼該如何獲取到當前組件的實例呢?這時能夠用到另外一個方法,即 getCurrentInstance

評論中反饋:在生產環境就沒有用,沒法獲得ctx上下文

<template>
 <p>{{ num }}</p>
</template>
<script>
import {ref, getCurrentInstance} from 'vue'
export default {
    setup() { 
        const num = ref(3)
        const instance = getCurrentInstance()
        console.log(instance)

        return {num}
    }
}
</script>

instance 中重點關注 ctxproxy 屬性,這兩個纔是咱們想要的 this。能夠看到 ctxproxy 的內容十分相似,只是後者相對於前者外部包裝了一層 proxy,由此可說明 proxy 是響應式的

useStore

在Vue2中使用 Vuex,咱們都是經過 this.$store 來與獲取到Vuex實例,但上一部分說了本來Vue2中的 this 的獲取方式不同了,而且咱們在Vue3的 getCurrentInstance().ctx 中也沒有發現 $store 這個屬性,那麼如何獲取到Vuex實例呢?這就要經過 vuex 中的一個方法了,即 useStore

// store 文件夾下的 index.js
import Vuex from 'vuex'

const store = Vuex.createStore({
    state: {
      name: '前端印象',
      age: 22
    },
    mutations: {
      ……
    },
    ……
})

// example.vue
<script>
// 從 vuex 中導入 useStore 方法
import {useStore} from 'vuex'
export default {
    setup() { 
        // 獲取 vuex 實例
        const store = useStore()

        console.log(store)
    }
}
</script>

而後接下來就能夠像以前同樣正常使用 vuex

參考:vue3經常使用api使用

相關文章
相關標籤/搜索