1前言
8.10號凌晨,尤雨溪在微博平臺官宣 Vue 3.2 版本正式發佈:
此版本包含一系列重要的新功能與性能改進,但並不涉及任何重大變更。本文主要介紹一些相對重要 Vue3.2新特性,如需瞭解更多請查閱官方文檔!
2新的 SFC 功能
關於單文件組件(SFC,即.vue 文件)的兩項功能已經由實驗狀態正式畢業,現提供穩定版本:
-
<script setup>
是一種編譯時語法糖,能夠極大改善在 SFC 中使用 Composition API 時的開發者體驗。 -
<style> v-bind
用於在 SFC<style>
標籤中啓用組件狀態驅動的動態 CSS 值。
1、<script setup>
在<script setup>
中,我們不必聲明export default
和setup
方法,這種寫法會自動將所有頂級變量、函數,均會自動暴露給模板(template)使用。我們先來通過一個例子,對比script setup
前後寫法的不同,直觀感受下setup
帶給我們的便利:
// script setup之前的寫法
<template>
<div>
<div>浪裏行舟</div>
<Card>{{ message }}</Card>
</div>
</template>
<script lang="ts">
import { ref, defineComponent } from "vue";
import Card from "./components/Card.vue";
export default defineComponent({
components: {
Card,
},
setup() {
const message = ref("vue 3.2 新特性 script setup");
return { message };
},
});
</script>
// script setup的寫法
<template>
<div>
<div>浪裏行舟</div>
<Card>{{message}}</Card>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import Card from "./components/Card.vue";
const message = ref("vue 3.2 新特性 script setup");
</script>
從上面的例子來看,<script setup>
語法省去了組件Card的註冊步驟,以及return變量message的語句,使得代碼更爲精簡。關於<script setup>
的使用還有些細節和注意事項,我將會在下一篇文章詳細介紹。
2、<style> v-bind
挺有趣的一個新特性,通過這個指令,Vue SFC 的 CSS 靈活性將大大提高。該指令適用於<script setup>
, 並支持 JavaScript 表達式(必須用引號括起來)。
<script setup>
import { ref } from "vue";
const color = ref("pink");
color.value = "green";
const fontSize = ref("18px");
</script>
<template>
<h2>浪裏行舟</h2>
<h1>Hello Vue3.2</h1>
<h2>{{ color }}</h2>
<button @click="color = 'red'">color red</button>
<button @click="color = 'yellow'">color yellow</button>
<button @click="color = 'blue'">color blue</button>
<button @click="fontSize = '40px'">fontSize 40px</button>
</template>
<style scoped>
h1 {
color: v-bind(color);
}
h2 {
font-size: v-bind(fontSize);
}
</style>
點擊按鈕更改color
或者 fontSize
的數值,可以看到頁面樣式也會響應式變化。其原理就是自定義屬性將通過內聯樣式應用於組件的根元素,並在數值更改時進行響應更新。
3v-memo
3.2 版本爲 Vue 的響應式系統帶來了一系列重大性能改進,具體包括:
-
更高效的 ref 實現(讀取速度提高約 260%,寫入速度提高約 50%) -
依賴項跟蹤速度提高約 40% -
內存使用量減少約 17%
新版本還提供新的 v-memo
指令,可實現對部分模板樹的記憶功能。當v-memo
命中時,不僅允許 Vue 跳過虛擬 DOM 差異、甚至可以完全跳過新 VNode 的創建步驟。雖然這個指令使用頻率不高,但它提供了一個逃生艙來在某些情況下(例如處理大型 v-for
列表)獲取最大性能。
<div v-for="user of users" :key="user.id" v-memo="[user.name]">
{{ user.name }}
</div>
這個例子使用v-memo
,不會重新創建虛擬元素,並且會重新使用前一個元素,除非v-memo
(此處爲用戶名)的條件發生變化。這可能看起來是一個很小的改進,但如果您渲染大量元素,它實際上是性能的巨大改進。
其實v-memo
可以接受一組條件,請看下面的例子:
<div v-for="user of users" :key="user.id" v-memo="[user.name, selectedUserId === user.id]">
<p :class="{ red: selectedUserId === user.id }">{{ user.name }}</p>
</div>
此時如果user.name
或selectedUserId
發生變化,div
則將更新。
4新 ref 語法糖(實驗性)
$ref()
避免在更新 ref 值時需要使用.value
,可以讓代碼更加精簡!請看下面例子:
<template>
<input type="number" v-model="count"> * 5€
<h1>{{ total }}</h1>
</template>
<script setup>
let count = $ref(0)
let total = $computed(() => count * 5)
</script>
⚠️注意:這還是一個實驗性特性,所以請謹慎使用,因爲它將來可能會發生變化。該提案還引入了其他新的語法糖,包括$computed()
、$fromRefs()
和$raw()
。
5Expose API
Vue 3.2 添加了一個新的 Expose API
來定義組件公開的內容。Expose API
的設想是提供一個像 expose({ ...publicMembers })
這樣的組合式 API,這樣組件的作者就可以在 setup()
中使用該 API 來精細設定公開暴露給其他組件的內容。
下例中,該組件只能公開其toggle
函數,而不能公開其collapsed
變量。
export default defineComponent({
setup(props, { expose }) {
const collapsed = ref(true)
const toggle = () => {
collapsed.value = !collapsed.value;
}
// only expose `toggle` to the parent component
expose({ toggle })
return { collapsed, toggle }
}
})
請注意,所有$
實例屬性都會自動公開,因此使用Collapse
的組件可以訪問$props
,$slots
以及其他。<script setup>
通過調用defineExpose()
函數使用時也可以這樣做。
當你在封裝組件時,如果嫌ref
中暴露的內容過多,不妨用 Expose API
來約束一下輸出吧!
6Effect Scope API
Vue 3.2版本引入了新的 Effect scope API
,用於創建一個effect Scope
對象,該對象可以捕獲在其中創建的反應性效果(例如computed
或 watchers
),以便可以將這些效果放在一起並輕鬆處理它們。它可以更輕鬆地在組件上下文之外使用 Vue 的響應式 API,同時也在組件之內解鎖了多種高級用例。Effect scope
是一種高級 API,主要供庫作者使用。
我們知道watch
, watchEffect
,computed
等都是綁定到一個特定的組件實例上的,在組件銷燬的時候會被 Vue 自動銷燬。這可確保應用程序沒有內存泄漏。但是如果你想在組件之外使用這些函數,例如在你正在編寫的庫中,你需要手動處理它們,請看下例:
import { ref, computed, stop, watchEffect } from 'vue';
const quantity = ref(0);
const price = ref(10);
const total = computed(() => quantity.value * price.value);
const stopWatch = watchEffect(() => console.log(`total changed to ${total.value}`));
let effectsToStop = [];
effectsToStop.push(() => stop(total));
effectsToStop.push(stopWatch);
const stopAll = () => {
effectsToStop.forEach(f => f())
effectsToStop = []
};
// calling `stopAll()` disposes of all effects
7.prop 和 .attr 修飾符
-
.prop
: 被用於強制綁定 DOM 屬性 (property) -
.attr
: 被用於強制綁定 DOM 屬性 (attribute)
v-bind 默認綁定到 DOM 節點的 attribute 上,使用.prop
修飾符後,設置的自定義屬性不會在渲染後的 HTML 標籤裏顯示,而.attr
修飾符則剛好相反!
.prop
修飾符用途:
-
通過自定義屬性存儲變量, 避免暴露數據 -
防止污染 HTML 結構
<input id="input" type="foo" value="11" :data.prop="inputData"></input>
// 渲染後HTML標籤結構
<input id="input" type="foo" value="11"></input>
看了它的用途就知道,如果你不想你的屬性顯示在html標籤裏面,就用.prop
修飾符吧!
另外這兩個修飾符有簡寫的語法:
<a :title.prop="firstTabTooltip" :aria-selected.attr="isFirstTabSelected">First tab</a>
<!-- 簡寫 -->
<a .title="firstTabTooltip" ^aria-selected="isFirstTabSelected">First tab</a>
8Web 組件
Vue 3.2 引入了新的 defineCustomElement
方法,可以使用 Vue 組件 API 輕鬆創建原生自定義元素:
import { defineCustomElement } from 'vue'
const MyVueElement = defineCustomElement({
// 常規 Vue 組件選項
})
// 註冊自定義元素。
// 註冊完成後,此頁面上的所有 `<my-vue-element>` 標籤
// 都將將升級。
customElements.define('my-vue-element', MyVueElement)
此 API 允許開發者們創建由 Vue 驅動的 UI 組件庫。這些庫可以支持任何框架選項,甚至能夠在無框架情況下正常使用。
9總結
以上諸多特性,最讓我感興趣的是setup script
,此語法使單個文件組件更簡單!只需要給 script
標籤添加一個 setup
屬性,那麼整個 script
就直接會變成setup
函數,所有頂級變量、函數,均會自動暴露給模板使用(無需再一個個 return了),開發效率將大大的提高!
以至於連尤大也在微博上呼籲大家:“如果你能用Vue3卻還在用 Options API,現在有了< script setup>沒有理由不換 Composition API了”
10參考資料
-
Vue 3.2 Released! -
Vue 3.2 Released! -
What's new in Vue 3.2? -
v-bind 指令常用修飾符 -
Vue3 官方文檔 -
Vue 3.2正式發佈,script setup + TS + Volar = 真香
本文分享自微信公衆號 - 前端自習課(FE-study)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。