Vue3.3等類庫最新特性及其使用

一、Vue3.3最新特性

Vue 3.3 “Rurouni Kenshin”——浪客劍心的最新版本主要目標(biāo)是優(yōu)化開發(fā)者的使用體驗(yàn)咏删,包括引入一些新的簡(jiǎn)化語法和宏惹想,以及在TypeScript方面的進(jìn)一步提升。

以下是主要的更新內(nèi)容:

1.為setup語法糖組件引入了泛型功能督函;
2.允許在組件文件中導(dǎo)入外部的ts類型嘀粱;
3.對(duì)defineEmits語法進(jìn)行了優(yōu)化;
4.新增defineSlots定義插槽類型辰狡;
5.新增defineModel來簡(jiǎn)化modelValue的語法锋叨;
6.Reactive Props 解構(gòu)
7.新增defineOptions定義組件名稱以及其他一些配置項(xiàng);
8.對(duì)toRef和toValue的功能進(jìn)行了增強(qiáng)宛篇。

接下來對(duì)這些改動(dòng)一一介紹

1.setup語法糖泛型

使用<script setup>的組件現(xiàn)在可以通過generic屬性接受泛型類型參數(shù)娃磺,一般情況下用不到,但有時(shí)候組件比較復(fù)雜時(shí)無法推斷類型的時(shí)候非常有用

<script setup lang="ts" generic="T">
import {defineProps} from "vue";
const props =  defineProps<{
  items: T[];
  selected: T;
}>();
</script>

2.支持導(dǎo)入外部ts類型

defineProps和defineEmits支持使用import外部導(dǎo)入的類型聲明叫倍。

<script setup lang="ts">
import type { People } from './type.ts';

// 使用導(dǎo)入的類型 + 交集類型(導(dǎo)入類型基礎(chǔ)上增加一個(gè)字段)
defineProps< People & { extraProp?: string }>() //在vue3.3之前不支持使用import導(dǎo)入的類型
</script>

generic 的值與 TypeScript 中 <...> 之間的參數(shù)列表用法完全相同偷卧。例如,您可以使用多個(gè)參數(shù)段标、extend 約束涯冠、默認(rèn)類型和引用導(dǎo)入的類型:

<script setup lang="ts" generic="T extends string | number, U extends Item">
import type { Item } from './types'
defineProps<{
  id: T
  list: U[]
}>()
</script>

3.defineEmits語法優(yōu)化

之前defineEmits的類型參數(shù)只支持函數(shù)調(diào)用簽名語法:

// 以前
const emit = defineEmits<{
  (e: 'foo', id: number): void
  (e: 'bar', name: string, ...rest: any[]): void
}>()
// 或者不定義類型
const emit = defineEmits(['update:modelValue'])

在vue3.3中可以簡(jiǎn)化為以下寫法,更加簡(jiǎn)潔

// 現(xiàn)在
const emit = defineEmits<{
  foo: [id: number]
  bar: [name: string, ...rest: any[]]
}>()

在類型字面量中逼庞,key 是事件名稱,value 是事件參數(shù)的數(shù)組類型瞻赶。
以前的函數(shù)調(diào)用簽名語法仍然受支持赛糟。

4.新增defineSlots

新的defineSlots宏可以用來聲明插槽的類型,例如:

子組件DefineSlots

<script setup lang="ts">
defineSlots<{
  default?: (props: { msg: string }) => any
  item?: (props: { id: number }) => any
}>()
</script>

其中砸逊,defineSlots中的item就是我們定義的插槽名稱璧南,props就是我們定義的插槽的參數(shù),any就是我們定義插槽的返回值师逸,msg司倚、id就是插槽的參數(shù)。

父組件

<template>
  <DefineSlots>
    <template #default="{msg}" >{{msg}}</template>
    <template #item="{id}" >{{id}}</template>
  </DefineSlots>
</template>

<script setup lang="ts">
import DefineSlots from './components/defineSlots.vue';
</script>

插槽函數(shù)的返回類型目前被忽略篓像。

試驗(yàn)性功能:

5.新增defineModel

用于簡(jiǎn)化自定義v-model雙向綁定語法动知,在vue3.3中此功能是實(shí)驗(yàn)性的,需要明確的選擇加入员辩。

// vite.config.js
export default {
  plugins: [
    vue({
      defineModel: true
    })
  ]
}

以前組件想要支持 v-model盒粮,需要兩個(gè)步驟:
1.聲明 props
2.在打算更新 props 時(shí),emit update:propName 事件

子組件支持 v-model 的寫法:

<template>
  <input :value="modelValue" @input="onInput" />
</template>

<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])

function onInput(e) {
  emit('update:modelValue', e.target.value)
}
</script>

簡(jiǎn)化后的寫法

<template>
  <input v-model="modelValue" />
</template>

<script setup>
const modelValue = defineModel()
// 也可以直接修改奠滑,等價(jià)于emit('update:modelValue', '新值')
// modelValue.value = '新的值'
</script>

6.Reactive Props 解構(gòu)

該功能可以解構(gòu)的 props 并保持響應(yīng)性丹皱,并提供了一種更符合人體工程學(xué)的方式來聲明 props 的默認(rèn)值:

<script setup>
import { watchEffect } from 'vue'

const { msg = 'hello' } = defineProps(['msg'])

watchEffect(() => {
  // 在 watch 和 computed 中使用 msg
  // 能夠正常收集依賴妒穴,就好像使用 props.msg
  console.log(`msg is: ${msg}`)
})
</script>

<template>{{ msg }}</template>

此功能是實(shí)驗(yàn)性的,需要明確的選擇加入摊崭。

// vite.config.js
export default {
  plugins: [
    vue({
      propsDestructure: true
    })
  ]
}

其它值得注意的功能:

7.新增 defineOptions

新的defineOptions宏允許直接在<script setup>中聲明組件選項(xiàng)讼油,而不需要單獨(dú)的<script>塊

當(dāng)我們想使用 mounted鉤子函數(shù)時(shí),會(huì)報(bào)錯(cuò)呢簸,因?yàn)?<script setup>會(huì)將所有的代碼都放在 setup函數(shù)中矮台,而 mounted是在 setup函數(shù)之后執(zhí)行的,所以會(huì)報(bào)錯(cuò)阔墩。
此外某些場(chǎng)景緩存頁面數(shù)據(jù)嘿架,可能需要設(shè)置組件名稱 name。

可以用 defineOptions 定義任意選項(xiàng)啸箫,但 props, emits, expose, slots 除外

<script setup>
import { onMounted } from 'vue';
// eslint-disable-next-line no-undef
defineOptions({
  name: 'DefineOptions',
  inheritAttrs: false,
  mounted() {
    console.log('mounted');
  }
})
onMounted(()=>{
  console.log('onMounted')
})
</script>

8.toRef和toValue增強(qiáng)

toRef已得到增強(qiáng)耸彪,將元素變成響應(yīng)式,支持將值/getter/現(xiàn)有refs規(guī)范化為refs:

// 等價(jià)于ref(1)
toRef(1)
// 創(chuàng)建一個(gè)readonly ref忘苛,在.value訪問時(shí)調(diào)用getter 
toRef(() => props.foo)
// 按原樣返回現(xiàn)有的引用
toRef(existingRef)

使用getter調(diào)用toRef類似于computed蝉娜,但當(dāng)getter只是執(zhí)行屬性訪問而沒有昂貴的計(jì)算時(shí),效率會(huì)更高扎唾。

新的toValue實(shí)用程序方法提供了相反的功能召川,將values / getters / refs標(biāo)準(zhǔn)化為值:

toValue(1) //       --> 1
toValue(ref(1)) //  --> 1
toValue(() => 1) // --> 1

toValue可以在composable中代替unref使用,這樣你的composable就可以接受getter作為反應(yīng)式數(shù)據(jù)源:

// 以前:分配不必要的中間引用
useFeature(computed(() => props.foo))
useFeature(toRef(props, 'foo'))

// 現(xiàn)在:更高效和簡(jiǎn)潔
useFeature(() => props.foo)

toRef和toValue之間的關(guān)系類似于ref和unref之間的關(guān)系胸遇,主要區(qū)別在于對(duì)getter函數(shù)的特殊處理荧呐。

9.依賴更新

依賴更新
升級(jí)到 3.3 時(shí),建議同時(shí)更新以下依賴項(xiàng):
volar / vue-tsc@^1.6.4
vite@^4.3.5
@vitejs/plugin-vue@^4.2.0
vue-loader@^17.1.0(如果使用 webpack 或 vue-cli)

二纸镊、Vue Router新特性

在使用vue-router4中params 進(jìn)行路由組件之間傳參

<script setup lang="ts">
import { useRouter } from 'vue-router'

const router = useRouter()
const params = { id: '1', name: 'wjj', phone: 123456789, age: 23 }
function toFirst() {
  router.push({ name: 'first', params })
}
</script>

在接收頁面嘗試渲染params傳遞的數(shù)據(jù):

template>
  <div>姓名:{{ route.params?.name }}</div>
  <div>電話:{{ route.params?.phone }}</div>
  <div>年齡:{{ route.params?.age }}</div>
</template>

<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
</script>

跳轉(zhuǎn)頁面接收不了并出現(xiàn)如下Vue Router警告:


警告

我們點(diǎn)擊連接后發(fā)現(xiàn)了原因:


github更新日志

也就是說倍阐,從Vue Router的2022-8-22 這次更新后,我們使用上面的方式在新頁面無法獲取逗威。

Vue也給我們提出了代替方案:

1.使用query的方式傳參

修改為query方式傳參數(shù)峰搪,注意query方式只能用路由表中的path,不是name凯旭,并且所有的參數(shù)都會(huì)顯示在URL地址上概耻。

<script setup lang="ts">
import { useRouter } from 'vue-router'

const router = useRouter()
const params = { id: '1', name: 'wjj', phone: 123456789, age: 23 }
function toFirst() {
  // query方式
  router.push({ path: '/first', query: params })
}
</script>
跳轉(zhuǎn)之后參數(shù)顯示在URL上

2.將數(shù)據(jù)放在pinia或者vuex這樣的狀態(tài)管理庫里面

實(shí)際工作中,咱們非必要不會(huì)使用這種方式罐呼。

3.使用動(dòng)態(tài)路由匹配

如果傳遞參數(shù)較少的情況下鞠柄,可以嘗試使用動(dòng)態(tài)路由匹配方式,只要修改一下path定義部分就可以了:

{
      // path: '/first',
      path: '/first/:id/:name/:phone/:age', // 動(dòng)態(tài)路由弄贿,修改一下path定義
      name: 'first',
      component: () => import('../views/FirstView.vue')
    }

跳轉(zhuǎn)頁面通過path春锋,接收頁面使用route.params

<script setup lang="ts">
import { useRouter } from 'vue-router'

const router = useRouter()
function toFirst() {
  // 動(dòng)態(tài)路由
  router.push({ path: '/first/1/wjj/123456789/23'})
}
</script>
<!--動(dòng)態(tài)路由方式-->
<p>姓名:{{ route.params?.name }}</p>
<p>電話:{{ route.params?.phone }}</p>
<p>年齡:{{ route.params?.age }}</p>

注意:如果使用了動(dòng)態(tài)路由匹配方式,path中的每個(gè)參數(shù)都是必須傳遞差凹,否則會(huì)報(bào)錯(cuò)期奔。
警告

個(gè)人覺得動(dòng)態(tài)路由匹配方式接收參數(shù)與params方式一樣侧馅,如果不把params參數(shù)寫在路由路徑上無法得到params參數(shù),雖然不算棄用了params呐萌,但是每次都把params參數(shù)都寫在路由路徑上也是非常麻煩的一件事馁痴。

4.使用HistoryAPI的方式

在跳轉(zhuǎn)頁面使用state參數(shù)

<script setup lang="ts">
import { useRouter } from 'vue-router'

const router = useRouter()
const params = { id: '1', name: 'wjj', phone: 123456789, age: 23 }
function toFirst() {
  // state
  router.push({ name: 'first', state: { params } })
}
</script>

跳轉(zhuǎn)后的頁面接收:

<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
const historyParams = history.state.params
</script>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市肺孤,隨后出現(xiàn)的幾起案子罗晕,更是在濱河造成了極大的恐慌,老刑警劉巖赠堵,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件小渊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡茫叭,警方通過查閱死者的電腦和手機(jī)酬屉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來揍愁,“玉大人呐萨,你說我怎么就攤上這事∶Ф冢” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵朽缎,是天一觀的道長(zhǎng)惨远。 經(jīng)常有香客問我,道長(zhǎng)话肖,這世上最難降的妖魔是什么锨络? 我笑而不...
    開封第一講書人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮狼牺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘礼患。我一直安慰自己是钥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開白布缅叠。 她就那樣靜靜地躺著悄泥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪肤粱。 梳的紋絲不亂的頭發(fā)上弹囚,一...
    開封第一講書人閱讀 51,198評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音领曼,去河邊找鬼鸥鹉。 笑死蛮穿,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的毁渗。 我是一名探鬼主播践磅,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼灸异!你這毒婦竟也來了府适?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤肺樟,失蹤者是張志新(化名)和其女友劉穎檐春,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體么伯,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡疟暖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蹦狂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片誓篱。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖凯楔,靈堂內(nèi)的尸體忽然破棺而出窜骄,到底是詐尸還是另有隱情,我是刑警寧澤摆屯,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布邻遏,位于F島的核電站,受9級(jí)特大地震影響虐骑,放射性物質(zhì)發(fā)生泄漏准验。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一廷没、第九天 我趴在偏房一處隱蔽的房頂上張望糊饱。 院中可真熱鬧,春花似錦颠黎、人聲如沸另锋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夭坪。三九已至,卻和暖如春过椎,著一層夾襖步出監(jiān)牢的瞬間室梅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留亡鼠,地道東北人赏殃。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像拆宛,于是被迫代替她去往敵國(guó)和親嗓奢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容