vue3常用的API使用簡介
vue3.x已經(jīng)發(fā)布了這么久,相關(guān)的生態(tài)也慢慢起來了,包括vite這個新的打包工具,在vue3.0學(xué)習(xí)過程中有一些實用性的api對比,希望能在開發(fā)中給大家做個示范,準(zhǔn)確的使用對應(yīng)的api去完成我們的項目開發(fā)
生命周期的變更
要特別說明一下的就是,setup 函數(shù)代替了 beforeCreate 和 created 兩個生命周期函數(shù),因此我們可以認為它的執(zhí)行時間在beforeCreate 和 created 之間
| Vue2 | Vue3 |
|---|---|
| beforeCreate | setup |
| created | setup |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeDestory | onBeforeUnmount |
| destoryed | onUnmounted |
了解過vue3的小伙伴兒都知道,現(xiàn)在使用都會用到setup函數(shù),關(guān)于在setup函數(shù)操作數(shù)據(jù),我們用例子說明會好一點
reactive
reactive 方法是用來創(chuàng)建一個響應(yīng)式的數(shù)據(jù)對象,該API也很好地解決了Vue2通過 defineProperty 實現(xiàn)數(shù)據(jù)響應(yīng)式的缺陷
用法很簡單,只需將數(shù)據(jù)作為參數(shù)傳入即可
<template>
<div id="app">
<!-- 4. 訪問響應(yīng)式數(shù)據(jù)對象中的 count -->
{{ state.count }}
</div>
</template>
<script>
// 1. 從 vue 中導(dǎo)入 reactive
import {reactive} from 'vue'
export default {
name: 'App',
setup() {
// 2. 創(chuàng)建響應(yīng)式的數(shù)據(jù)對象
const state = reactive({count: 3})
// 3. 將響應(yīng)式數(shù)據(jù)對象state return 出去,供template使用
return {state}
}
}
</script>
ref
在介紹 setup 函數(shù)時,我們使用了 ref 函數(shù)包裝了一個響應(yīng)式的數(shù)據(jù)對象,這里表面上看上去跟 reactive 好像功能一模一樣啊,確實差不多,因為 ref 就是通過 reactive 包裝了一個對象 ,然后是將值傳給該對象中的 value 屬性,這也就解釋了為什么每次訪問時我們都需要加上 .value
我們可以簡單地把 ref(obj) 理解為這個樣子 reactive({value: obj})
<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>

注意: 這里指的 .value 是在 setup 函數(shù)中訪問 ref 包裝后的對象時才需要加的,在 template 模板中訪問時是不需要的,因為在編譯時,會自動識別其是否為 ref 包裝過的
那么我們到底該如何選擇 ref 和 reactive 呢?
建議:
- 基本類型值(String 、Nmuber 、Boolean 等)或單值對象(類似像 {count: 3} 這樣只有一個屬性值的對象)使用 ref
- 引用類型值(Object 、Array)使用 reactive
我們在vue2.x中獲取元素標(biāo)簽是用 ref ,vue3.x我們要獲取元素標(biāo)簽怎么辦呢?
<template>
<div>
<div ref="el">div元素</div>
</div>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
setup() {
// 創(chuàng)建一個DOM引用,名稱必須與元素的ref屬性名相同
const el = ref(null)
// 在掛載后才能通過 el 獲取到目標(biāo)元素
onMounted(() => {
el.value.innerHTML = '內(nèi)容被修改'
})
// 把創(chuàng)建的引用 return 出去
return {el}
}
}
</script>
獲取元素的操作一共分為以下幾個步驟:
- 先給目標(biāo)元素的 ref 屬性設(shè)置一個值,假設(shè)為 el
- 然后在 setup 函數(shù)中調(diào)用 ref 函數(shù),值為 null,并賦值給變量 el,這里要注意,該變量名必須與我們給元素設(shè)置的 ref 屬性名相同
- 把對元素的引用變量 el 返回(return)出去
補充:設(shè)置的元素引用變量只有在組件掛載后才能訪問到,因此在掛載前對元素進行操作都是無效的
當(dāng)然如果我們引用的是一個組件元素,那么獲得的將是該組件的實例對象
toRef
toRef 是將某個對象中的某個值轉(zhuǎn)化為響應(yīng)式數(shù)據(jù),其接收兩個參數(shù),第一個參數(shù)為 obj 對象;第二個參數(shù)為對象中的屬性名
<script>
// 1. 導(dǎo)入 toRef
import {toRef} from 'vue'
export default {
setup() {
const obj = {count: 3}
// 2. 將 obj 對象中屬性count的值轉(zhuǎn)化為響應(yīng)式數(shù)據(jù)
const state = toRef(obj, 'count')
// 3. 將toRef包裝過的數(shù)據(jù)對象返回供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('響應(yīng)式數(shù)據(jù)對象:', state1);
}
function add2() {
state2.value ++
console.log('原始值:', obj);
console.log('響應(yīng)式數(shù)據(jù)對象:', state2);
}
return {state1, state2, add1, add2}
}
}
</script>
ref 是對原數(shù)據(jù)的一個拷貝,不會影響到原始值,同時響應(yīng)式數(shù)據(jù)對象值改變后會同步更新視圖
toRef 是對原數(shù)據(jù)的一個引用,會影響到原始值,但是響應(yīng)式數(shù)據(jù)對象值改變后會不會更新視圖
toRefs
將傳入的對象里所有的屬性的值都轉(zhuǎn)化為響應(yīng)式數(shù)據(jù)對象,該函數(shù)支持一個參數(shù),即 obj 對象
<script>
// 1. 導(dǎo)入 toRefs
import {toRefs} from 'vue'
export default {
setup() {
const obj = {
name: '前端印象',
age: 22,
gender: 0
}
// 2. 將 obj 對象中屬性count的值轉(zhuǎn)化為響應(yīng)式數(shù)據(jù)
const state = toRefs(obj)
// 3. 打印查看一下
console.log(state)
}
}
</script>
返回的是一個對象,對象里包含了每一個包裝過后的響應(yīng)式數(shù)據(jù)對象
shallowReactive
聽這個API的名稱就知道,這是一個淺層的 reactive,難道意思就是原本的 reactive 是深層的唄,沒錯,這是一個用于性能優(yōu)化的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,雖然值發(fā)生了改變,但是視圖卻沒有進行更新;
當(dāng)我們點擊了第一個按鈕,改變了第一層的 a 時,整個視圖進行了更新;
由此可說明,shallowReactive 監(jiān)聽了第一層屬性的值,一旦發(fā)生改變,則更新視圖
shallowRef
這是一個淺層的 ref,與 shallowReactive 一樣是拿來做性能優(yōu)化的,配合triggerRef ,調(diào)用它就可以立馬更新視圖,其接收一個參數(shù) state ,即需要更新的 ref 對象
shallowReactive 是監(jiān)聽對象第一層的數(shù)據(jù)變化用于驅(qū)動視圖更新,那么 shallowRef 則是監(jiān)聽 .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
// 修改值后立即驅(qū)動視圖更新
triggerRef(state)
console.log(state);
}
return {state, change}
}
}
</script>
toRaw
toRaw 方法是用于獲取 ref 或 reactive 對象的原始數(shù)據(jù)的
<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 對象中獲取到的是原始數(shù)據(jù),因此我們就可以很方便的通過修改原始數(shù)據(jù)的值而不更新視圖來做一些性能優(yōu)化了
注意: 補充一句,當(dāng) toRaw 方法接收的參數(shù)是 ref 對象時,需要加上 .value 才能獲取到原始數(shù)據(jù)對象
markRaw
markRaw 方法可以將原始數(shù)據(jù)標(biāo)記為非響應(yīng)式的,即使用 ref 或 reactive 將其包裝,仍無法實現(xiàn)數(shù)據(jù)響應(yīng)式,其接收一個參數(shù),即原始數(shù)據(jù),并返回被標(biāo)記后的數(shù)據(jù)。即使我們修改了值也不會更新視圖了,即沒有實現(xiàn)數(shù)據(jù)響應(yīng)式
<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標(biāo)記原始數(shù)據(jù)obj, 使其數(shù)據(jù)更新不再被追蹤
const raw = markRaw(obj)
// 試圖用reactive包裝raw, 使其變成響應(yīng)式數(shù)據(jù)
const state = reactive(raw)
function change() {
state.age = 90
console.log(state);
}
return {state, change}
}
}
</script>
watchEffect
watchEffect 它與 watch 的區(qū)別主要有以下幾點:
- 不需要手動傳入依賴
- 每次初始化時會執(zhí)行一次回調(diào)函數(shù)來自動獲取依賴
- 無法獲取到原值,只能得到變化后的值
<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 方法一樣先給其傳入一個依賴,而是直接指定了一個回調(diào)函數(shù)
當(dāng)組件初始化時,將該回調(diào)函數(shù)執(zhí)行一次,自動獲取到需要檢測的數(shù)據(jù)是 state.count 和 state.name
根據(jù)以上特征,我們可以自行選擇使用哪一個監(jiān)聽器
getCurrentInstance
我們都知道在Vue2的任何一個組件中想要獲取當(dāng)前組件的實例可以通過 this 來得到,而在Vue3中我們大量的代碼都在 setup 函數(shù)中運行,并且在該函數(shù)中 this 指向的是undefined,那么該如何獲取到當(dāng)前組件的實例呢?這時可以用到另一個方法,即 getCurrentInstance
<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 中重點關(guān)注 ctx 和 proxy 屬性,這兩個才是我們想要的 this。可以看到 ctx 和 proxy 的內(nèi)容十分類似,只是后者相對于前者外部包裝了一層 proxy,由此可說明 proxy 是響應(yīng)式的
useStore
在Vue2中使用 Vuex,我們都是通過 this.$store 來與獲取到Vuex實例,但上一部分說了原本Vue2中的 this 的獲取方式不一樣了,并且我們在Vue3的 getCurrentInstance().ctx 中也沒有發(fā)現(xiàn) $store 這個屬性,那么如何獲取到Vuex實例呢?這就要通過 vuex 中的一個方法了,即 useStore
// store 文件夾下的 index.js
import Vuex from 'vuex'
const store = Vuex.createStore({
state: {
name: '前端印象',
age: 22
},
mutations: {
……
},
……
})
// example.vue
<script>
// 從 vuex 中導(dǎo)入 useStore 方法
import {useStore} from 'vuex'
export default {
setup() {
// 獲取 vuex 實例
const store = useStore()
console.log(store)
}
}
</script>
然后接下來就可以像之前一樣正常使用 vuex 了
以上就是vue3常用的API使用簡介的詳細內(nèi)容,更多關(guān)于vue 常用的api使用的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解mpvue中使用vant時需要注意的onChange事件的坑
這篇文章主要介紹了詳解mpvue中使用vant時需要注意的onChange事件的坑,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-05-05
vueJS簡單的點擊顯示與隱藏的效果【實現(xiàn)代碼】
下面小編就為大家?guī)硪黄獀ueJS簡單的點擊顯示與隱藏的效果【實現(xiàn)代碼】。小編覺得挺不錯的,現(xiàn)在分享給大家,一起跟隨小編過來看看吧2016-05-05
VueJs使用Amaze ui調(diào)整列表和內(nèi)容頁面
這篇文章主要介紹了VueJs 填坑日記之使用Amaze ui調(diào)整列表和內(nèi)容頁面,需要的朋友可以參考下2017-11-11
詳解vue開發(fā)中調(diào)用微信jssdk的問題
這篇文章主要介紹了vue開發(fā)中調(diào)用微信jssdk的問題,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04

