日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

快速使用Vue3最新的15个常用API

發(fā)布時(shí)間:2023/12/9 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 快速使用Vue3最新的15个常用API 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

之前我寫(xiě)了一篇博客介紹了Vue3的新特性,簡(jiǎn)單了解了一下Vue3都有哪些特色,并且在文末帶大家稍微體驗(yàn)了一下Vue3中 Compsition API 的簡(jiǎn)單使用

上一篇文章地址:緊跟尤大的腳步提前體驗(yàn)Vue3新特性,你不會(huì)還沒(méi)了解過(guò)Vue3吧

因?yàn)檫@個(gè)月的月初給自己定了個(gè)小目標(biāo),學(xué)完Vue3的基本使用,并使用Vue3親手做一個(gè)小項(xiàng)目(稍微透露一下,我制作的是一個(gè)小工具,現(xiàn)在已經(jīng)完成了90%了,這個(gè)月月底之前會(huì)通過(guò)博客的形式向大家展示,并且提供設(shè)計(jì)思路,大家敬請(qǐng)期待……),本文會(huì)頻繁地對(duì)比Vue2來(lái)介紹Vue3,也將對(duì)各個(gè)API結(jié)合代碼實(shí)例講解,這既是對(duì)自己知識(shí)的總結(jié),也希望能幫助到大家

一、前言

大家都知道,現(xiàn)在Vue3的各個(gè)版本已經(jīng)陸續(xù)發(fā)布了,并且有很多的團(tuán)隊(duì)已經(jīng)著手各個(gè)庫(kù)的開(kāi)發(fā)與Vue2向Vue3的升級(jí),我們當(dāng)然也不能落后,所以趕緊將你手中的Vue2升級(jí)到Vue3,跟著本文一起學(xué)習(xí)新的API吧

升級(jí)的方法可以點(diǎn)擊本文開(kāi)頭的文章,在上一篇文章中有個(gè)保姆級(jí)別的教程告訴大家如何升級(jí)

二、正文

Vue2每次都把整個(gè)Vue導(dǎo)入,例如Vue2的 main.js 文件中的代碼

import?Vue?from?'vue' import?App?from?'./App.vue'Vue.config.productionTip?=?falsenew?Vue({render:?h?=>?h(App) }).$mount('#app')

但很明顯我們的項(xiàng)目中不可能用到Vue所有的API,因此很多模塊其實(shí)是沒(méi)有用的

那么在Vue3中,對(duì)外暴露了很多的API供開(kāi)發(fā)者使用,我們可以根據(jù)自己的需求,將所需要的API從Vue中導(dǎo)入。例如 main.js 中的代碼

import?{?createApp?}?from?'vue'; import?App?from?'./App.vue'createApp(App).mount('#app')

利用了 import 和 export 的導(dǎo)入導(dǎo)出語(yǔ)法,實(shí)現(xiàn)了按需打包模塊的功能,項(xiàng)目打包后的文件體積明顯小了很多

這也是我們本文需要對(duì) Vue3 API 進(jìn)行詳細(xì)了解的原因

(1)setup

setup 函數(shù)也是 Compsition API 的入口函數(shù),我們的變量、方法都是在該函數(shù)里定義的,來(lái)看一下使用方法

<template><div?id="app"><p>{{?number?}}</p><button?@click="add">增加</button></div> </template><script> //?1.?從?vue?中引入?ref?函數(shù) import?{ref}?from?'vue' export?default?{name:?'App',setup()?{//?2.?用?ref?函數(shù)包裝一個(gè)響應(yīng)式變量?numberlet?number?=?ref(0)//?3.?設(shè)定一個(gè)方法function?add()?{//?number是被ref函數(shù)包裝過(guò)了的,其值保存在.value中number.value?++}//?4.?將?number?和?add?返回出去,供template中使用return?{number,?add}}} </script>

上述代碼中用到了 ref 函數(shù),下面會(huì)詳細(xì)講解,在這里你只需要理解它的作用是包裝一個(gè)響應(yīng)式的數(shù)據(jù)即可,并且你可以將 ref 函數(shù)包裝過(guò)的變量看作是Vue2 data 中的變量

這樣就簡(jiǎn)單實(shí)現(xiàn)了一個(gè)點(diǎn)擊按鈕數(shù)字加1的功能


在Vue2中,我們?cè)L問(wèn) data 或 props 中的變量,都是通過(guò)類(lèi)似 this.number 這樣的形式去獲取的,但要特別注意的是,在setup中,this 指向的是 undefined,也就是說(shuō)不能再向Vue2一樣通過(guò) this 去獲取變量了

那么到底該如何獲取到 props 中的數(shù)據(jù)呢?

其實(shí) setup 函數(shù)還有兩個(gè)參數(shù),分別是 props 、context,前者存儲(chǔ)著定義當(dāng)前組件允許外界傳遞過(guò)來(lái)的參數(shù)名稱(chēng)以及對(duì)應(yīng)的值;后者是一個(gè)上下文對(duì)象,能從中訪問(wèn)到 attr 、emit 、slots

其中 emit 就是我們熟悉的Vue2中與父組件通信的方法,可以直接拿來(lái)調(diào)用

(2)生命周期

Vue2中有 beforeCreate 、created 、beforeMount 、mounted 、beforeUpdate 等生命周期函數(shù)

而在Vue3中,這些生命周期部分有所變化,并且調(diào)用的方式也有所改變,下面放上一張變化圖來(lái)簡(jiǎn)單了解一下

Vue2Vue3
beforeCreatesetup
createdsetup
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeDestoryonBeforeUnmount
destoryedonUnmounted

Vue3的這些生命周期調(diào)用也很簡(jiǎn)單,同樣是先從 vue 中導(dǎo)入,再進(jìn)行直接調(diào)用

<template><div?id="app"></div> </template><script> //?1.?從?vue?中引入?多個(gè)生命周期函數(shù) import?{onBeforeMount,?onMounted,?onBeforeUpdate,?onUpdated,?onBeforeUnmount,?unMounted}?from?'vue' export?default?{name:?'App',setup()?{onBeforeMount(()?=>?{//?在掛載前執(zhí)行某些代碼})onMounted(()?=>?{//?在掛載后執(zhí)行某些代碼})onBeforeUpdate(()?=>?{//?在更新前前執(zhí)行某些代碼})onUpdated(()?=>?{//?在更新后執(zhí)行某些代碼})onBeforeUnmount(()?=>?{//?在組件銷(xiāo)毀前執(zhí)行某些代碼})unMounted(()?=>?{//?在組件銷(xiāo)毀后執(zhí)行某些代碼})return?{}}} </script>

要特別說(shuō)明一下的就是,setup 函數(shù)代替了 beforeCreate 和 created 兩個(gè)生命周期函數(shù),因此我們可以認(rèn)為它的執(zhí)行時(shí)間在beforeCreate 和 created 之間

(3)reactive

reactive 方法是用來(lái)創(chuàng)建一個(gè)響應(yīng)式的數(shù)據(jù)對(duì)象,該API也很好地解決了Vue2通過(guò) defineProperty 實(shí)現(xiàn)數(shù)據(jù)響應(yīng)式的缺陷

用法很簡(jiǎn)單,只需將數(shù)據(jù)作為參數(shù)傳入即可,代碼如下

<template><div?id="app"><!--?4.?訪問(wèn)響應(yīng)式數(shù)據(jù)對(duì)象中的?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ù)對(duì)象const?state?=?reactive({count:?3})//?3.?將響應(yīng)式數(shù)據(jù)對(duì)象state?return?出去,供template使用return?{state}} } </script>

(4)ref

在介紹 setup 函數(shù)時(shí),我們使用了 ref 函數(shù)包裝了一個(gè)響應(yīng)式的數(shù)據(jù)對(duì)象,這里表面上看上去跟 reactive 好像功能一模一樣啊,確實(shí)差不多,因?yàn)?ref 就是通過(guò) reactive 包裝了一個(gè)對(duì)象 ,然后是將值傳給該對(duì)象中的 value 屬性,這也就解釋了為什么每次訪問(wèn)時(shí)我們都需要加上 .value

我們可以簡(jiǎn)單地把 ref(obj) 理解為這個(gè)樣子 reactive({value: obj})

這里我們寫(xiě)一段代碼來(lái)具體看一下

<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>

來(lái)看一下打印結(jié)果


注意: 這里指的 .value 是在 setup 函數(shù)中訪問(wèn) ref 包裝后的對(duì)象時(shí)才需要加的,在 template 模板中訪問(wèn)時(shí)是不需要的,因?yàn)樵诰幾g時(shí),會(huì)自動(dòng)識(shí)別其是否為 ref 包裝過(guò)的

那么我們到底該如何選擇 ref 和 reactive 呢?

建議:

  • 基本類(lèi)型值(String 、Nmuber 、Boolean 等)或單值對(duì)象(類(lèi)似像 {count: 3} 這樣只有一個(gè)屬性值的對(duì)象)使用 ref

  • 引用類(lèi)型值(Object 、Array)使用 reactive

  • (5)toRef

    toRef 是將某個(gè)對(duì)象中的某個(gè)值轉(zhuǎn)化為響應(yīng)式數(shù)據(jù),其接收兩個(gè)參數(shù),第一個(gè)參數(shù)為 obj 對(duì)象;第二個(gè)參數(shù)為對(duì)象中的屬性名

    代碼如下:

    <script> //?1.?導(dǎo)入?toRef import?{toRef}?from?'vue' export?default?{setup()?{const?obj?=?{count:?3}//?2.?將?obj?對(duì)象中屬性count的值轉(zhuǎn)化為響應(yīng)式數(shù)據(jù)const?state?=?toRef(obj,?'count')//?3.?將toRef包裝過(guò)的數(shù)據(jù)對(duì)象返回供template使用return?{state}} } </script>

    但其實(shí)表面上看上去 toRef 這個(gè)API好像非常的沒(méi)用,因?yàn)檫@個(gè)功能也可以用 ref 實(shí)現(xiàn),代碼如下

    <script> //?1.?導(dǎo)入?ref import?{ref}?from?'vue' export?default?{setup()?{const?obj?=?{count:?3}//?2.?將?obj?對(duì)象中屬性count的值轉(zhuǎn)化為響應(yīng)式數(shù)據(jù)const?state?=?ref(obj.count)//?3.?將ref包裝過(guò)的數(shù)據(jù)對(duì)象返回供template使用return?{state}} } </script>

    乍一看好像還真是,其實(shí)這兩者是有區(qū)別的,我們可以通過(guò)一個(gè)案例來(lái)比較一下,代碼如下

    <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ù)對(duì)象:',?state1);}function?add2()?{state2.value?++console.log('原始值:',?obj);console.log('響應(yīng)式數(shù)據(jù)對(duì)象:',?state2);}return?{state1,?state2,?add1,?add2}} } </script>

    我們分別用 ref 和 toRef 將 obj 中的 count 轉(zhuǎn)化為響應(yīng)式,并聲明了兩個(gè)方法分別使 count 值增加,每次增加后打印一下原始值 obj 和被包裝過(guò)的響應(yīng)式數(shù)據(jù)對(duì)象,同時(shí)還要看看視圖的變化

    ref:


    可以看到,在對(duì)響應(yīng)式數(shù)據(jù)的值進(jìn)行 +1 操作后,視圖改變了,原始值未改變,響應(yīng)式數(shù)據(jù)對(duì)象的值也改變了,這說(shuō)明 ref 是對(duì)原數(shù)據(jù)的一個(gè)拷貝,不會(huì)影響到原始值,同時(shí)響應(yīng)式數(shù)據(jù)對(duì)象值改變后會(huì)同步更新視圖

    toRef:


    可以看到,在對(duì)響應(yīng)式數(shù)據(jù)的值進(jìn)行 +1 操作后,視圖未發(fā)生改變,原始值改變了,響應(yīng)式數(shù)據(jù)對(duì)象的值也改變了,這說(shuō)明 toRef 是對(duì)原數(shù)據(jù)的一個(gè)引用,會(huì)影響到原始值,但是響應(yīng)式數(shù)據(jù)對(duì)象值改變后會(huì)不會(huì)更新視圖

    總結(jié):

  • ref 是對(duì)傳入數(shù)據(jù)的拷貝;toRef 是對(duì)傳入數(shù)據(jù)的引用

  • ref 的值改變會(huì)更新視圖;toRef 的值改變不會(huì)更新視圖

  • (6)toRefs

    了解完 toRef 后,就很好理解 toRefs 了,其作用就是將傳入的對(duì)象里所有的屬性的值都轉(zhuǎn)化為響應(yīng)式數(shù)據(jù)對(duì)象,該函數(shù)支持一個(gè)參數(shù),即 obj 對(duì)象

    我們來(lái)看一下它的基本使用

    <script> //?1.?導(dǎo)入?toRefs import?{toRefs}?from?'vue' export?default?{setup()?{const?obj?=?{name:?'前端印象',age:?22,gender:?0}//?2.?將?obj?對(duì)象中屬性count的值轉(zhuǎn)化為響應(yīng)式數(shù)據(jù)const?state?=?toRefs(obj)//?3.?打印查看一下console.log(state)} } </script>

    打印結(jié)果如下:

    返回的是一個(gè)對(duì)象,對(duì)象里包含了每一個(gè)包裝過(guò)后的響應(yīng)式數(shù)據(jù)對(duì)象

    (7)shallowReactive

    聽(tīng)這個(gè)API的名稱(chēng)就知道,這是一個(gè)漸層的 reactive,難道意思就是原本的 reactive 是深層的唄,沒(méi)錯(cuò),這是一個(gè)用于性能優(yōu)化的API

    其實(shí)將 obj 作為參數(shù)傳遞給 reactive 生成響應(yīng)式數(shù)據(jù)對(duì)象時(shí),若 obj 的層級(jí)不止一層,那么會(huì)將每一層都用 Proxy 包裝一次,我們來(lái)驗(yàn)證一下

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

    來(lái)看一下打印結(jié)果:


    設(shè)想一下如果一個(gè)對(duì)象層級(jí)比較深,那么每一層都用 Proxy 包裝后,對(duì)于性能是非常不友好的

    接下來(lái)我們?cè)賮?lái)看看 shallowReactive

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

    來(lái)看一下打印結(jié)果:


    結(jié)果非常的明了了,只有第一層被 Proxy 處理了,也就是說(shuō)只有修改第一層的值時(shí),才會(huì)響應(yīng)式更新,代碼如下:

    <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?=?8state.first.second.c?=?9console.log(state);}return?{state}} } </script>

    來(lái)看一下具體過(guò)程:

    首先我們點(diǎn)擊了第二個(gè)按鈕,改變了第二層的 b 和第三層的 c,雖然值發(fā)生了改變,但是視圖卻沒(méi)有進(jìn)行更新;

    當(dāng)我們點(diǎn)擊了第一個(gè)按鈕,改變了第一層的 a 時(shí),整個(gè)視圖進(jìn)行了更新;

    由此可說(shuō)明,shallowReactive 監(jiān)聽(tīng)了第一層屬性的值,一旦發(fā)生改變,則更新視圖

    (8)shallowRef

    這是一個(gè)淺層的 ref,與 shallowReactive 一樣是拿來(lái)做性能優(yōu)化的

    shallowReactive 是監(jiān)聽(tīng)對(duì)象第一層的數(shù)據(jù)變化用于驅(qū)動(dòng)視圖更新,那么 shallowRef 則是監(jiān)聽(tīng) .value 的值的變化來(lái)更新視圖的

    我們來(lái)看一下具體代碼

    <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?{shallowRef}?from?'vue' export?default?{setup()?{const?obj?=?{a:?1,first:?{b:?2,second:?{c:?3}}}const?state?=?shallowRef(obj)console.log(state);function?change1()?{//?直接將state.value重新賦值state.value?=?{a:?7,first:?{b:?8,second:?{c:?9}}}}function?change2()?{state.value.first.b?=?8state.value.first.second.c?=?9console.log(state);}return?{state,?change1,?change2}} } </script>

    首先看一下被 shallowRef 包裝過(guò)后是怎樣的結(jié)構(gòu)


    然后再來(lái)看看改變其值會(huì)有什么變化


    我們先點(diǎn)擊了第二個(gè)按鈕,發(fā)現(xiàn)數(shù)據(jù)確實(shí)被改變了,但是視圖并沒(méi)隨之更新;

    于是點(diǎn)擊了第一個(gè)按鈕,即將整個(gè) .value 重新賦值了,視圖就立馬更新了

    這么一看,未免也太過(guò)麻煩了,改個(gè)數(shù)據(jù)還要重新賦值,不要擔(dān)心,此時(shí)我們可以用到另一個(gè)API,叫做 triggerRef ,調(diào)用它就可以立馬更新視圖,其接收一個(gè)參數(shù) state ,即需要更新的 ref 對(duì)象

    我們來(lái)使用一下

    <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?=?8state.value.first.second.c?=?9//?修改值后立即驅(qū)動(dòng)視圖更新triggerRef(state)console.log(state);}return?{state,?change}} } </script>

    我們來(lái)看一下具體過(guò)程


    可以看到,我們沒(méi)有給 .value 重新賦值,只是在修改值后,調(diào)用了 triggerRef 就實(shí)現(xiàn)了視圖的更新

    (9)toRaw

    toRaw 方法是用于獲取 ref 或 reactive 對(duì)象的原始數(shù)據(jù)的

    先來(lái)看一段代碼

    <template><p>{{?state.name?}}</p><p>{{?state.age?}}</p><button?@click="change">改變</button> </template><script> import?{reactive}?from?'vue' export?default?{setup()?{const?obj?=?{name:?'前端印象',age:?22}const?state?=?reactive(obj)?function?change()?{state.age?=?90console.log(obj);?//?打印原始數(shù)據(jù)objconsole.log(state);??//?打印?reactive對(duì)象}return?{state,?change}} } </script>

    來(lái)看看具體過(guò)程

    我們改變了 reactive 對(duì)象中的數(shù)據(jù),于是看到原始數(shù)據(jù) obj 和被 reactive 包裝過(guò)的對(duì)象的值都發(fā)生了變化,由此我們可以看出,這兩者是一個(gè)引用關(guān)系

    那么此時(shí)我們就想了,那如果直接改變?cè)紨?shù)據(jù) obj 的值,會(huì)怎么樣呢?答案是:reactive 的值也會(huì)跟著改變,但是視圖不會(huì)更新

    由此可見(jiàn),當(dāng)我們想修改數(shù)據(jù),但不想讓視圖更新時(shí),可以選擇直接修改原始數(shù)據(jù)上的值,因此需要先獲取到原始數(shù)據(jù),我們可以使用 Vue3 提供的 toRaw 方法

    toRaw 接收一個(gè)參數(shù),即 ref 對(duì)象或 reactive 對(duì)象

    <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 對(duì)象中獲取到的是原始數(shù)據(jù),因此我們就可以很方便的通過(guò)修改原始數(shù)據(jù)的值而不更新視圖來(lái)做一些性能優(yōu)化了

    注意: 補(bǔ)充一句,當(dāng) toRaw 方法接收的參數(shù)是 ref 對(duì)象時(shí),需要加上 .value 才能獲取到原始數(shù)據(jù)對(duì)象

    (10)markRaw

    markRaw 方法可以將原始數(shù)據(jù)標(biāo)記為非響應(yīng)式的,即使用 ref 或 reactive 將其包裝,仍無(wú)法實(shí)現(xiàn)數(shù)據(jù)響應(yīng)式,其接收一個(gè)參數(shù),即原始數(shù)據(jù),并返回被標(biāo)記后的數(shù)據(jù)

    我們來(lái)看一下代碼

    <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}//?通過(guò)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?=?90console.log(state);}return?{state,?change}} } </script>

    我們來(lái)看一下在被 markRaw 方法處理過(guò)后的數(shù)據(jù)是否還能被 reactive 包裝成響應(yīng)式數(shù)據(jù)

    從圖中可以看到,即使我們修改了值也不會(huì)更新視圖了,即沒(méi)有實(shí)現(xiàn)數(shù)據(jù)響應(yīng)式

    (11)provide && inject

    與 Vue2中的 provide 和 inject 作用相同,只不過(guò)在Vue3中需要手動(dòng)從 vue 中導(dǎo)入

    這里簡(jiǎn)單說(shuō)明一下這兩個(gè)方法的作用:

    • provide :向子組件以及子孫組件傳遞數(shù)據(jù)。接收兩個(gè)參數(shù),第一個(gè)參數(shù)是 key,即數(shù)據(jù)的名稱(chēng);第二個(gè)參數(shù)為 value,即數(shù)據(jù)的值

    • inject :接收父組件或祖先組件傳遞過(guò)來(lái)的數(shù)據(jù)。接收一個(gè)參數(shù) key,即父組件或祖先組件傳遞的數(shù)據(jù)名稱(chēng)

    假設(shè)這有三個(gè)組件,分別是 A.vue 、B.vue 、C.vue,其中 B.vue 是 A.vue 的子組件,C.vue 是 B.vue 的子組件

    //?A.vue <script> import?{provide}?from?'vue' export?default?{setup()?{const?obj=?{name:?'前端印象',age:?22}//?向子組件以及子孫組件傳遞名為info的數(shù)據(jù)provide('info',?obj)} } </script>//?B.vue <script> import?{inject}?from?'vue' export?default?{setup()?{?//?接收A.vue傳遞過(guò)來(lái)的數(shù)據(jù)inject('info')??//?{name:?'前端印象',?age:?22}} } </script>//?C.vue <script> import?{inject}?from?'vue' export?default?{setup()?{?//?接收A.vue傳遞過(guò)來(lái)的數(shù)據(jù)inject('info')??//?{name:?'前端印象',?age:?22}} } </script>

    (12)watch && watchEffect

    watch 和 watchEffect 都是用來(lái)監(jiān)視某項(xiàng)數(shù)據(jù)變化從而執(zhí)行指定的操作的,但用法上還是有所區(qū)別

    watch:watch( source, cb, [options] )

    參數(shù)說(shuō)明:

    • source:可以是表達(dá)式或函數(shù),用于指定監(jiān)聽(tīng)的依賴(lài)對(duì)象

    • cb:依賴(lài)對(duì)象變化后執(zhí)行的回調(diào)函數(shù)

    • options:可參數(shù),可以配置的屬性有 immediate(立即觸發(fā)回調(diào)函數(shù))、deep(深度監(jiān)聽(tīng))

    當(dāng)監(jiān)聽(tīng) ref 類(lèi)型時(shí):

    <script> import?{ref,?watch}?from?'vue' export?default?{setup()?{?const?state?=?ref(0)watch(state,?(newValue,?oldValue)?=>?{console.log(`原值為${oldValue}`)console.log(`新值為${newValue}`)/* 1秒后打印結(jié)果:原值為0新值為1*/})//?1秒后將state值+1setTimeout(()?=>?{state.value?++},?1000)} } </script>

    當(dāng)監(jiān)聽(tīng) reactive 類(lèi)型時(shí):

    <script> import?{reactive,?watch}?from?'vue' export?default?{setup()?{?const?state?=?reactive({count:?0})watch(()?=>?state.count,?(newValue,?oldValue)?=>?{console.log(`原值為${oldValue}`)console.log(`新值為${newValue}`)/* 1秒后打印結(jié)果:原值為0新值為1*/})//?1秒后將state.count的值+1setTimeout(()?=>?{state.count?++},?1000)} } </script>

    當(dāng)同時(shí)監(jiān)聽(tīng)多個(gè)值時(shí):

    <script> import?{reactive,?watch}?from?'vue' export?default?{setup()?{?const?state?=?reactive({?count:?0,?name:?'zs'?})watch([()?=>?state.count,?()?=>?state.name],?([newCount,?newName],?[oldvCount,?oldvName])?=>?{console.log(oldvCount)?//?舊的?count?值console.log(newCount)?//?新的?count?值console.log(oldName)?//?舊的?name?值console.log(newvName)?//?新的?name?值})setTimeout(()?=>?{state.count?++state.name?=?'ls'},?1000)} } </script>

    因?yàn)?watch 方法的第一個(gè)參數(shù)我們已經(jīng)指定了監(jiān)聽(tīng)的對(duì)象,因此當(dāng)組件初始化時(shí),不會(huì)執(zhí)行第二個(gè)參數(shù)中的回調(diào)函數(shù),若我們想讓其初始化時(shí)就先執(zhí)行一遍,可以在第三個(gè)參數(shù)對(duì)象中設(shè)置 immediate: true

    watch 方法默認(rèn)是漸層的監(jiān)聽(tīng)我們指定的數(shù)據(jù),例如如果監(jiān)聽(tīng)的數(shù)據(jù)有多層嵌套,深層的數(shù)據(jù)變化不會(huì)觸發(fā)監(jiān)聽(tīng)的回調(diào),若我們想要其對(duì)深層數(shù)據(jù)也進(jìn)行監(jiān)聽(tīng),可以在第三個(gè)參數(shù)對(duì)象中設(shè)置 deep: true

    補(bǔ)充: watch方法會(huì)返回一個(gè)stop方法,若想要停止監(jiān)聽(tīng),便可直接執(zhí)行該stop函數(shù)

    接下來(lái)再來(lái)聊聊 watchEffect,它與 watch 的區(qū)別主要有以下幾點(diǎn):

  • 不需要手動(dòng)傳入依賴(lài)

  • 每次初始化時(shí)會(huì)執(zhí)行一次回調(diào)函數(shù)來(lái)自動(dòng)獲取依賴(lài)

  • 無(wú)法獲取到原值,只能得到變化后的值

  • 來(lái)看一下該方法如何使用:

    <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)/*??初始化時(shí)打印:0zs1秒后打印:1ls*/})setTimeout(()?=>?{state.count?++state.name?=?'ls'},?1000)} } </script>

    從上述代碼中可以看出,我們并沒(méi)有像 watch 方法一樣先給其傳入一個(gè)依賴(lài),而是直接指定了一個(gè)回調(diào)函數(shù)

    當(dāng)組件初始化時(shí),將該回調(diào)函數(shù)執(zhí)行一次,自動(dòng)獲取到需要檢測(cè)的數(shù)據(jù)是 state.count 和 state.name

    根據(jù)以上特征,我們可以自行選擇使用哪一個(gè)監(jiān)聽(tīng)器

    (13)getCurrentInstance

    我們都知道在Vue2的任何一個(gè)組件中想要獲取當(dāng)前組件的實(shí)例可以通過(guò) this 來(lái)得到,而在Vue3中我們大量的代碼都在 setup 函數(shù)中運(yùn)行,并且在該函數(shù)中 this 指向的是 undefined,那么該如何獲取到當(dāng)前組件的實(shí)例呢?

    這時(shí)可以用到另一個(gè)方法,即 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>

    我們來(lái)看一下其打印結(jié)果

    因?yàn)?instance 包含的內(nèi)容太多,所以沒(méi)截完整,但是主要的內(nèi)容都在圖上了,我們重點(diǎn)來(lái)看一下 ctx 和 proxy,因?yàn)檫@兩個(gè)才是我們想要的 this 的內(nèi)容

    可以看到 ctx 和 proxy 的內(nèi)容十分類(lèi)似,只是后者相對(duì)于前者外部包裝了一層 proxy,由此可說(shuō)明 proxy 是響應(yīng)式的

    (14)useStore

    在Vue2中使用 Vuex,我們都是通過(guò) this.$store 來(lái)與獲取到Vuex實(shí)例,但上一部分說(shuō)了原本Vue2中的 this 的獲取方式不一樣了,并且我們?cè)赩ue3的 getCurrentInstance().ctx 中也沒(méi)有發(fā)現(xiàn) $store 這個(gè)屬性,那么如何獲取到Vuex實(shí)例呢?這就要通過(guò) vuex 中的一個(gè)方法了,即 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?實(shí)例const?store?=?useStore()console.log(store)} } </script>

    我們來(lái)看一下打印結(jié)果

    然后接下來(lái)就可以像之前一樣正常使用 vuex 了

    (15)獲取標(biāo)簽元素

    最后再補(bǔ)充一個(gè) ref 另外的作用,那就是可以獲取到標(biāo)簽元素或組件

    在Vue2中,我們獲取元素都是通過(guò)給元素一個(gè) ref 屬性,然后通過(guò) this.$refs.xx 來(lái)訪問(wèn)的,但這在Vue3中已經(jīng)不再適用了

    接下來(lái)看看Vue3中是如何獲取元素的吧

    <template><div><div?ref="el">div元素</div></div> </template><script> import?{?ref,?onMounted?}?from?'vue' export?default?{setup()?{//?創(chuàng)建一個(gè)DOM引用,名稱(chēng)必須與元素的ref屬性名相同const?el?=?ref(null)//?在掛載后才能通過(guò)?el?獲取到目標(biāo)元素onMounted(()?=>?{el.value.innerHTML?=?'內(nèi)容被修改'})//?把創(chuàng)建的引用?return?出去return?{el}} } </script>

    獲取元素的操作一共分為以下幾個(gè)步驟:

  • 先給目標(biāo)元素的 ref 屬性設(shè)置一個(gè)值,假設(shè)為 el

  • 然后在 setup 函數(shù)中調(diào)用 ref 函數(shù),值為 null,并賦值給變量 el,這里要注意,該變量名必須與我們給元素設(shè)置的 ref 屬性名相同

  • 把對(duì)元素的引用變量 el 返回(return)出去

  • 補(bǔ)充:設(shè)置的元素引用變量只有在組件掛載后才能訪問(wèn)到,因此在掛載前對(duì)元素進(jìn)行操作都是無(wú)效的

    當(dāng)然如果我們引用的是一個(gè)組件元素,那么獲得的將是該組件的實(shí)例對(duì)象,這里就不做過(guò)多的演示了

    三、結(jié)束語(yǔ)

    本文也是筆者對(duì)Vue3的學(xué)習(xí)與理解。因?yàn)樵谥皩W(xué)習(xí)的過(guò)程中也查閱了大量的文檔資料,并不斷地測(cè)試摸索,以及在Vue3項(xiàng)目中的心得體會(huì),都讓我對(duì)Vue3有了更深的認(rèn)識(shí),與此同時(shí),我在各個(gè)社區(qū)或者是社交群里都發(fā)現(xiàn)很多小伙伴對(duì)Vue3的API都不太熟悉,甚至不知道有這些API,所以我就寫(xiě)下了這篇總結(jié)文章,將我所知道、所理解的都分享給大家

    推薦閱讀

    我在阿里招前端,我該怎么幫你?(文末有福利)
    如何拿下阿里巴巴 P6 的前端 Offer
    如何準(zhǔn)備阿里P6/P7前端面試--項(xiàng)目經(jīng)歷準(zhǔn)備篇
    大廠面試官常問(wèn)的亮點(diǎn),該如何做出?
    如何從初級(jí)到專(zhuān)家(P4-P7)打破成長(zhǎng)瓶頸和有效突破
    若川知乎問(wèn)答:2年前端經(jīng)驗(yàn),做的項(xiàng)目沒(méi)什么技術(shù)含量,怎么辦?

    末尾

    你好,我是若川,江湖人稱(chēng)菜如若川,歷時(shí)一年只寫(xiě)了一個(gè)學(xué)習(xí)源碼整體架構(gòu)系列~(點(diǎn)擊藍(lán)字了解我)

  • 關(guān)注我的公眾號(hào)若川視野,回復(fù)"pdf" 領(lǐng)取前端優(yōu)質(zhì)書(shū)籍pdf

  • 我的博客地址:https://lxchuan12.gitee.io?歡迎收藏

  • 覺(jué)得文章不錯(cuò),可以點(diǎn)個(gè)在看呀^_^另外歡迎留言交流~

  • 小提醒:若川視野公眾號(hào)面試、源碼等文章合集在菜單欄中間【源碼精選】按鈕,歡迎點(diǎn)擊閱讀

    總結(jié)

    以上是生活随笔為你收集整理的快速使用Vue3最新的15个常用API的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。