Vue3.x 關於組件的那些變化(新手必看篇)


一、組件內的 data 為什么總是函數形式?

我們試着先做一個計數器案例,把 data 的返回形式修改成一個對象。具體的代碼如下:

<template>
 <div>
  <button @click="num++">+</button>
   {{num}}
  <button @click="num--">-</button>
 </div>
</template>
<script>
const retData = {
 num:0
}
export default {
 data(){
  return retData
 }
}
</script>

 

運行結果,看着是正常的,並無異常。但我們都知道,vue 項目中,之所以采用組件形式,就是為了重復多次使用,所以我們多次使用我們的組件試試。

神奇的效果發生了,當我們改變第一個組件的數值時,第二個組件的數據也被修改。修改第二個組件的時候,第一個組件的數據也同步更新。

Vue3.x 關於組件的那些變化(新手必看篇)

 

原因:同一個組件被復用多次,會創建多個實例,如果data是一個對象的話,這些實例用的是同一個構造函數,指針指向的就會是同一個地方,就導致了兩個組件的數據會同時更新。

為了保證組件內的數據各自獨立,不會相互影響,要求每個組件的data必須是函數形式,目的就是把數據放入一個新對象內,這樣就不會出現上述問題了。

說這的主要意義就是告訴我們,在 Vue3.x 中的 data 選項總是為函數形式,返回響應式數據。

Vue2.x VS Vue3.x 實例創建

Vue3.x 關於組件的那些變化(新手必看篇)

 

二、函數式組件的變化

在Vue3.x中,functional:true 組件選項被移除。vue3.x 不推薦使用函數式組件。

有些小伙伴就會驚嘆,媽呀,俺都不知道函數式組件是啥,你說得再簡單我也不懂吶,所以就講講函數式組件干啥的,原來的 functional 屬性放哪?

2.1、在Vue2.x中的函數式組件:

函數式組件也是組件的一種類型,主要用來定義那些沒有響應數據,也不需要任何生命周期鈎子函數,只 props 來接收傳遞來的數據。

類型1:基於模板的函數式組件

<template functional >
 <div>
  函數式組件內容
 </div>
</template>

 

類型2:組件注冊

Vue.componenet('fun-comp':{
 functional:true,
 props:{
  msg:{
   type:String,
   default:'組件數據'
  }
 },
 render:(h,context)=>{
  return h('div',['組件內容','++',context.props.msg])
 }
})

 

類型3:中間件實現 render 方法

// FunComps.js 文件代碼
export default {
 functional:true,
 props:{
  render:{
   type:Function
  },
  params:{}
 },
 render:(h,ctx)=>{
  return ctx.props.render(h,ctx.props.params)
 }
}

//組件調用
<fun-comp :render="renderHandle" :params="['111','222']" />

 

renderHandle 這個函數,在外層可以任意控制,這樣不但節省開銷,而且復用性也很高。

2.2、在Vue3.x中的函數式組件:

在 SFC 中不能使用 functional 特性聲明是函數式組件,移除了 functional:true 特性。

// 新建一個 FunComp.vue 文件
<script>
import { h } from "vue"
function Footer(props,context){
 return h(`h${props.level}`,context.attrs , context.slots )
}
Footer.props = ['level']
export default Footer
</script>

//使用函數式組件
<template>
 <FunComp level="1.0.0" >Vue3.x函數式組件內容</FunComp>
</template>
<script >
import FunComp from '../../components/FunComp.vue'
export default{
 component:{
  FunComp
 },
}
</script>

 

這下應該清楚到底移除的屬性在哪了!接着看看異步組件有什么改變。。。

三、異步組件的變化

Vue3.x 異步組件要求使用 defineAsyncComponent 方法創建。

由於 Vue3 中函數式組件必須定義為純函數,所以異步組件有如下變化:

  1. 必須明確地使用 defineAsyncComponent 方法包裹
  2. component 選項已經被重命名為 loader
  3. loader 函數不再接收 resolve 和 reject 回調方法 。且必須返回一個 Promise 對象 。

3.1、不帶配置的異步組件對比

在 Vue2.x中異步組件使用:

{
 path:'/',
 component: ()=> import("@/view/home/index")
}

 

在 Vue3.x 中異步組件使用:

import { defineAsyncComponent } from 'vue'

{
 path:"/",
 component:defineAsyncComponent(()=>{ import("@/view/home/index.vue") })
}

 

3.2、帶配置的異步組件

const asyncPageWithOptions = defineAsyncComponent({
 loader:()=> import("../view/index/index.vue"),
 delay:200,
 timeout:3000,
 errorComponent:ErrorComponent,
 loadingComponent:LoadingComponent
})

 

loader 選項是以前的 component 選項。

四、自定義組件白名單的變化

Vue3.x中,自定義元素檢測發生在模板編譯時,如果要添加 vue 之外的自定義元素,需要在編譯器選項中設置 isCustomElement 選項。
使用構建工具時,模板都會用 vue-loader 預編譯,在 vite.config.js 中配置它提供的 vueCompilerOption 即可:

import { defineConfig,vueCompilerOption } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
 plugins: [vue()],
 vueCompilerOptions:{
  isCustomElement:tag => tag==='pie-chart'
 }
})

 

此時遇到 pie-chart 元素時,直接跳過,不對其進行編譯。

五、動態組件

vue3.x 中設置動態組件時,is 屬性只能用於 component 標簽上。

使用方法:

<component :is="currentView"></component>
//currentView 是一個表達式

 

讓多個組件使用同一個掛載點,並動態切換組件。

5.1、動態組件的緩存

好多時候多個組件來回切換時,組件的實例都是重新創建的,而我們需要保存它的狀態,此時就需要緩存動態組件。

在Vue2.x中:

<keep-alive>
 <component :is="currentView"></component>
</keep-alive>

 

在 Vue3.x中:keep-alive 必須使用在 router-view內部

<router-view>
 <keep-alive>
  <component :is="currentView"></component>
 </keep-alive>
</router-view>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM