Vue3 中有哪些值得深究的知識(shí)點(diǎn)?
眾所周知,前端技術(shù)一直更新很快,這不 vue3 也問(wèn)世這么久了,今天就來(lái)給大家分享下vue3中值得注意的知識(shí)點(diǎn)。
1、createApp
vue2 和 vue3 在創(chuàng)建實(shí)例時(shí),有很大的區(qū)別,具體對(duì)比如下:
- //Vue 2
- Vue.use({
- router,
- store,
- render:h=>h(App)
- }).$mount("#app")
- //Vue 3
- createApp(App).use(router).use(store).mount("#app")
vue2 創(chuàng)建實(shí)例,使用的是 new Vue() 對(duì)應(yīng)的 router、store 都是其中一部分參數(shù)。
而 vue3 中,使用 createApp 創(chuàng)建應(yīng)用實(shí)例,router、store 被當(dāng)作插件通過(guò)鏈?zhǔn)秸{(diào)用。
在 vue2 中,創(chuàng)建多個(gè)實(shí)例的話,如果有 mixin、prototype 等時(shí),容易造成實(shí)例污染。而 createApp 方法創(chuàng)建的是一個(gè)全新的實(shí)例,可以有效地避免這個(gè)問(wèn)題。所以在vue3中,可以任意地創(chuàng)建多個(gè)實(shí)例。
2、setup
vue2 中選項(xiàng)式開發(fā)的,而 vue3 采用組合式開發(fā),也可以向下兼容選項(xiàng)式開發(fā)。
setup 函數(shù)就是 vue3 中 Composition API 的入口,是處于生命周期鉤子函數(shù) beforeCreate 和 created 兩個(gè)函數(shù)之間,所以 setup 中的屬性和方法無(wú)法在外部使用。如果需要使用的話,必須 return 暴露出去。
對(duì)比一下 vue2 和 vue3 中 data 和 method 使用區(qū)別:
- // vue2
- export default{
- data(){
- return{
- name:"熱愛(ài)前端的小姐姐"
- },
- methods:{
- print(){
- console.log("打印")
- }
- }
- }
- }
- // vue3
- export default{
- setup(){
- const name="熱愛(ài)前端的小姐姐"
- function print(){
- console.log("打印")
- }
- return { name , print }
- }
- }
vue2 中,this 是我們的???,隨處可見(jiàn)它的蹤影。我們?cè)?setup 中加入 this 的打印,試著查看下結(jié)果,發(fā)現(xiàn)運(yùn)行結(jié)果是 undefined。
所以在 setup 內(nèi)無(wú)法使用 this 以及掛載 this 相關(guān)的東西。
所以 setup 函數(shù)提供了兩個(gè)參數(shù):
- setup(props,context){
- //props 是響應(yīng)式數(shù)據(jù),不能直接解構(gòu)賦值
- //context 非響應(yīng)式對(duì)象,可以直接解構(gòu)使用
- // Attribute (非響應(yīng)式對(duì)象)
- console.log(context.attrs)
- // 插槽 (非響應(yīng)式對(duì)象)
- console.log(context.slots)
- // 觸發(fā)事件 (方法)
- console.log(context.emit)
- }
3、script setup 語(yǔ)法糖
簡(jiǎn)化上述 setup 組合式 API 的寫法,屬于 vue3 的新語(yǔ)法糖。
特點(diǎn):
- 定義的屬性和方法無(wú)需 return,可以直接使用。
- 自動(dòng)注冊(cè)組件,不再需要 components 內(nèi)注冊(cè)組件。
大大簡(jiǎn)化上述 setup() 的代碼。
4、鉤子函數(shù)
vue2 使用生命周期函數(shù)時(shí),直接使用就好了。如:
- // vue2
- export default{
- beforeCreate(){
- },
- mounted(){
- }
- }
但是在 vue3 組合式 API 中,通過(guò)生命周期鉤子前面加 on 來(lái)訪問(wèn),使用之前必須引入。如:
- // vue3
- <script setup>
- import { onMounted } from "vue"
- onMounted(()=>{
- })
- </script>
由于 setup 是圍繞 beforeCreate 和 created 生命周期鉤子運(yùn)行的,所以在 setup 內(nèi)不需要這兩個(gè)鉤子函數(shù),剩余的都是一樣的。
官方提供生命周期鉤子:

5、teleport 傳送門
teleport 傳送門可以把內(nèi)部的元素綁定到任意父元素上,使用方式簡(jiǎn)單靈活。
使用方式:
- <teleport to="body"></teleport>
to 屬性是指定 teleport 中內(nèi)容加入的 DOM 元素,可以是標(biāo)簽名、類名或 id 。
- //標(biāo)簽名 。上述實(shí)例就是加入body元素內(nèi),使用的是標(biāo)簽名。
- <teleport to="body"></teleport>
- //類名。如:to=".className"
- <teleport to=".className"></teleport>
- //id名
- <teleport to="#idName"></teleport>
優(yōu)點(diǎn):多個(gè)組件嵌套層次過(guò)多時(shí),樣式層級(jí)處理麻煩,使用 teleport 可以把元素剝離出來(lái),設(shè)置樣式方便,同時(shí) vue 控制狀態(tài)也方便。
6、mixin 混入
mixin 對(duì)象會(huì)把多個(gè)組件公用的選項(xiàng)提取出來(lái),需要的組件內(nèi)引入,管理方便。在 vue3 中 mixin 使用較少。
使用方式:
- <script>
- const myMixin = {
- data(){
- return {name:'熱愛(ài)前端的小姐姐'}
- }
- }
- export default {
- mixins:[myMixin],
- data(){
- return {
- qdr:"前端人"
- }
- }
- }
- </script>
使用時(shí),可以引入多個(gè) mixin 對(duì)象。使用注意事項(xiàng):
- mixin 對(duì)象與組件包含相同選項(xiàng)時(shí),會(huì)自動(dòng)合并。
- mixin 對(duì)象與組件相同選項(xiàng)內(nèi)擁有相同屬性時(shí),就近原則,優(yōu)先繼承實(shí)例內(nèi)的值。
- mixin 和組件包含相同的鉤子函數(shù)時(shí),會(huì)合并執(zhí)行,優(yōu)先執(zhí)行 mixin 中的鉤子函數(shù)。
- mixin 自定義屬性與實(shí)例中沖突時(shí),可以通過(guò) optionMergeStrategies 定義優(yōu)先級(jí)。
7、自定義指令
全局自定義指令:
vue2 的 directive 掛載到 Vue 對(duì)象上。
vue3 的 directive 掛載到 app 上,如:
- //Vue 2
- Vue.directive('name',opt)
- //Vue 3
- const app = createApp(App)
- app.directive("name",options)
- app.mount("#app")
局部自定義指令:與 vue2 寫法相同。
在 vue3 中自定義指令生命周期鉤子函數(shù)有一部分改變,鉤子函數(shù)分別為:
- created
- beforeMounted
- mounted
- beforeUpdate
- updated
- beforeUnmounted
- unmounted
8、ref、reactive
ref 作用是讓基礎(chǔ)類型數(shù)據(jù)具備響應(yīng)式。
reactive 讓引用數(shù)據(jù)類型具備響應(yīng)式能力。
ref 和 reactive 包裹數(shù)據(jù),使數(shù)據(jù)具備響應(yīng)式,在使用之前需要先引入。
使用方法如:
- <script setup>
- import { ref , reactive } from "vue"
- let mood = ref("value")
- let me = reactive({
- str:value,
- })
- </script>
setup + ref + reactive 就可以實(shí)現(xiàn) vue2 中 data 的響應(yīng)式功能,所以 setup 能夠替換掉 data 。
9、toRefs、toRef
toRefs 解構(gòu) props 傳遞的數(shù)據(jù),由于父向子組件通過(guò) props 傳值是響應(yīng)式的,使用 ES6 解構(gòu)會(huì)消除響應(yīng)特性,所以使用 toRefs 。
- <script setup>
- const props = defineProps({
- selectNum:Number,
- allNum:Number,
- })
- const { selectNum, allNum } = toRefs(props)
- </script>
toRef 也是解構(gòu)數(shù)據(jù),主要是對(duì)可選參數(shù)處理,運(yùn)行時(shí)先檢查 解構(gòu)的數(shù)據(jù)中是否存在該屬性,如果存在就繼承,不存在則會(huì)創(chuàng)建一個(gè)屬性,這樣就不會(huì)報(bào)錯(cuò)了。
- const str = toRef( props, 'str' )
10、watch、watchEffect 新用法
watch 、watchEffect 都是偵聽器。
watch 會(huì)監(jiān)聽某個(gè)基礎(chǔ)類型數(shù)據(jù)或引用數(shù)據(jù)類型的某個(gè)具體屬性。
vue3 使用 watch 之前,必須引入。
- //vue2
- watch:{
- mood(curVal,preVal){
- console.log('cur',curVal);//最新值
- console.log('pre',preVal);//修改之前的值
- }
- }
- //vue3
- import { watch } from "vue"
- watch(
- name ,
- ( curVal , preVal )=>{ //業(yè)務(wù)處理 },
- options
- )
watchEffect 監(jiān)聽的是引用數(shù)據(jù)類型的所有屬性,不需要指定是哪個(gè)具體的屬性,一旦運(yùn)行,就會(huì)立刻執(zhí)行。
watchEffect 使用之前也必須引入。
- import { watchEffect } from "vue"
- let obj = reactive({ name:'qq',sex:'女'})
- watchEffect(() => {
- console.log('name',obj.name);
- console.log('sex' , obj.sex);
- })
watch 與 watchEffect 對(duì)比:
- watch 運(yùn)行的時(shí)候不會(huì)立刻執(zhí)行, watchEffect 立即執(zhí)行。
- watch 更加具體,需要指定監(jiān)聽的誰(shuí),watchEffect 不要執(zhí)行具體監(jiān)聽誰(shuí),回調(diào)函數(shù)內(nèi)直接使用就可以,比較抽象。
- watch 回調(diào)內(nèi)可以訪問(wèn)到修改之前的值,watchEffect 只能訪問(wèn)最新的值。
- watch 可通過(guò)配置實(shí)現(xiàn) watchEffect 的前兩個(gè)特性。
11、computed 新用法
computed 計(jì)算屬性
選項(xiàng)式 API 中 vue2 和 vue3 使用相同。
組合式 API 中,使用之前需要引入。
- // 選項(xiàng)式
- computed:{
- sum(){
- return this.num1+ this.num2
- }
- }
- //組合式
- import { ref, computed } from "vue"
- export default{
- setup(){
- const num1 = ref(1)
- const num2 = ref(1)
- let sum = computed(()=>{
- return num1.value + num2.value
- })
- }
- }
或者,它可以使用一個(gè)帶有 get 和 set 函數(shù)的對(duì)象來(lái)創(chuàng)建一個(gè)可寫的對(duì)象。
- let mul = computed({
- get:()=>{
- return num1.value *10
- },
- set:(value)=>{
- return num1.value = value/10
- }
- })
在vue3.2+內(nèi),computed 可接受一個(gè)帶有 onTrack 和 onTrigger 選項(xiàng)的對(duì)象作為第二個(gè)參數(shù):
- onTrack 會(huì)在某個(gè)響應(yīng)式 property 或 ref 作為依賴被追蹤時(shí)調(diào)用。
- onTrigger 會(huì)在偵聽回調(diào)被某個(gè)依賴的修改觸發(fā)時(shí)調(diào)用。
12、provide / inject
provide/inject 類似于消息的訂閱和發(fā)布,provide 提供或發(fā)送數(shù)據(jù)或方法, inject 接收數(shù)據(jù)或方法。
優(yōu)點(diǎn):組件嵌套層級(jí)較多,父組件向子組件、多個(gè)孫組件傳值時(shí),傳遞數(shù)據(jù)需要一級(jí)一級(jí)向下傳遞,比較麻煩,使用 project 和 inject 很方便地解決了這個(gè)問(wèn)題。
- //vue2
- export default{
- provide:{
- info:"提供數(shù)據(jù)"
- }
- }
- //接收數(shù)據(jù)
- export default{
- inject:['info'],
- mounted(){
- console.log("接收數(shù)據(jù):", this.info) // 接收數(shù)據(jù):提供數(shù)據(jù)
- }
- }
- //vue3
- <script setup>
- import { provide } from "vue"
- provide( 'info', "值" )
- </script>
- //接收數(shù)據(jù)
- <script setup>
- import { inject } from "vue"
- const info = inject( 'info', "設(shè)置默認(rèn)值" )
- </script>
13、readonly
readonly 只讀函數(shù),使用之后該數(shù)據(jù)只能使用,不能修改,修改時(shí)會(huì)有警告。
父子組件之間傳值時(shí),如果傳遞的是響應(yīng)式數(shù)據(jù),子組件修改的時(shí)候,父組件的也會(huì)更新,這樣就容易造成狀態(tài)混亂,不符合 vue 的單項(xiàng)數(shù)據(jù)流。
如果使用 readonly ,保證數(shù)據(jù)在其他組件內(nèi)只能使用,并不能修改,規(guī)避混亂。
14、獲取真實(shí)DOM
vue2 使用 $ref 獲取真實(shí)DOM。
vue3 使用 ref 獲取真實(shí)DOM。與上述的 ref 不同。
- <div ref="box" class="test" id="boxtest">獲取真實(shí)DOM</div>
- //vue2
- <script>
- export default{
- mounted(){
- console.log('box', this.$refs.box);
- }
- }
- </script>
- //vue3
- <script setup>
- const box = ref(null)
- onMounted(()=>{
- console.log('box',box.value);
- })
- </script>
15、vue3 中的 vuex4
createStore 函數(shù)創(chuàng)建新的 store 實(shí)例。使用之前需要先引入。
- import { createApp } from 'vue'
- import App from './App.vue'
- import { createStore } from "vuex"
- const store = createStore({
- state(){
- return{
- num:1,
- }
- }
- })
- const app = createApp(App)
- app.use(store)
- app.mount('#app')
組件內(nèi)使用 store 時(shí),通過(guò) useStore 引入,使用之前也需要引入。
- import { useStore } from "vuex"
- const store = useStore()
使用的時(shí)候,與低版本都是一樣的。使用 state 內(nèi)數(shù)據(jù)時(shí),可以通過(guò) toRefs 解構(gòu)。
16、v-slot
v-slot 指令只能用在 template 或組件上,否則就會(huì)報(bào)錯(cuò)。
簡(jiǎn)化 slot、slot-scope 作用域插槽的功能,相比更加強(qiáng)大,代碼效率更高。
使用:
- <child-com>
- <template v-slot:header>
- 頭部
- </template>
- <template v-slot:body>
- 內(nèi)容
- </template>
- </child-com>
簡(jiǎn)寫:
- <child-com>
- <template #header>
- 頭部
- </template>
- <template #body>
- 內(nèi)容
- </template>
- </child-com>
17、vue3 中的 vue-router4
createRouter 創(chuàng)建 router 實(shí)例,之前的 mode 改為 history 。
- import { createRouter,createWebHashHistory } from "vue-router";
- const routes = []
- const router = createRouter({
- history:createWebHashHistory('/'),
- routes
- })
- export default router
在 main.js 內(nèi)引入的時(shí)候,通過(guò) use 引用。
- import { createApp } from 'vue'
- import App from './App.vue'
- import router from "./router/index"
- const app = createApp(App)
- app.use(router)
- app.mount('#app')
關(guān)于 vue-router4 更新挺多的,更多知識(shí)請(qǐng)閱讀《 vue-router 4 你真的熟練嗎?》文章。
18、render
在 vue3 中,render 函數(shù)的參數(shù)發(fā)生了改變,之前的 h 去掉,變成全局引入,虛擬節(jié)點(diǎn)具備扁平的屬性結(jié)構(gòu)。
vue3中 render 應(yīng)用
- import { h } from "vue"
- export default {
- render(){
- return h("div", {}, content)
- }
- }
【編輯推薦】