1. 程式人生 > 其它 >vue3.2版本新特性

vue3.2版本新特性

Vue 3.2 版本包括許多重要的新功能和效能改進,但並不包含重大更改。
Vue 3.2 原文連結

https://blog.vuejs.org/posts/vue-3.2.html

主要更新如下:

1. 新的單檔案元件功能
<script setup> 是一種編譯時語法糖,可在 SFC 內使用 Composition API 時極大地提升工作效率。
<style> v-bind 在 SFC 標籤中啟用元件狀態驅動的動態 CSS 值。<style>

起初 vue3.0 暴露變數必須 return 出來,template中才能使用

<script>
import Foo from './Foo.vue'
import Bar from './Bar.vue'
export default {
setup (props) {
console.log(props)
return {
ok: Math.random(),
Foo,
Bar
}
}
}
</script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
vue3.2 中 只需要在 script 標籤上加上 setup 屬性,元件在編譯的過程中程式碼執行的上下是 setup() 函式中。所有ES模組匯出都被認為是暴露給上下文的值,幷包含在 setup() 返回物件中。

<template>
<Foo/>
<Bar/>
<component :is="ok ? Foo : Bar"/>
</template>

<script setup="props">
export { default as Foo } from './Foo.vue'
export { default as Bar } from './Bar.vue'
export const ok = Math.random()
console.log(props)
</script>

1
2
3
4
5
6
7
8
9
10
11
12
13
其實 script setup 就相當於在編譯執行是把程式碼放到了 setup 函式中執行,然後把匯出的變數定義到上下文中,幷包含在返回的物件中。

style v-bind 使用如下:

<template>
<button @click="color = color === 'red' ? 'green' : 'red'"> Color is: {{ color }} </button>
</template>

<script setup>
import { ref } from 'vue'
export const color = ref('red')
</script>

<style scoped>
button { color: v-bind(color);}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
2. 網頁元件
Web Components 是一套不同的技術,允許您建立可重用的自定義元素——將它們的功能與程式碼的其餘部分封裝在一起——並在您的 Web 應用程式中使用它們。

Vue 3.2 引入了一種使用 Vue 元件 API 輕鬆建立原生自定義元素的新方法:defineCustomElement

import { defineCustomElement } from 'vue'

const MyVueElement = defineCustomElement({
// normal Vue component options here
})

// Register the custom element.
// After registration, all `<my-vue-element>` tags
// on the page will be upgraded.
customElements.define('my-vue-element', MyVueElement)
1
2
3
4
5
6
7
8
9
10
更多網頁元件學習:
Web_Components
web-components-examples

3. 效能改進
主要表現在介面渲染速度的提升和記憶體使用減少上:

更高效的 ref 實現(約 260% 的讀取速度/約 50% 的寫入速度)
約 40% 更快的依賴跟蹤
記憶體使用量減少約 17%
模板編譯器也得到了一些改進:
建立普通元素 VNode 的速度提高了約 200%
最後,有一個新v-memo指令提供了記憶模板樹的一部分的能力。一v-memo允許Vue跳過虛擬DOM版本比較,建立新的虛擬節點。雖然很少需要,但它提供了一個逃生艙,以在某些情況下(例如大型v-for列表)擠出最大效能。

4.服務端渲染
3.2 中的包現在提供了一個 ES 模組構建,它也與 Node.js 內建模組分離。這使得捆綁和利用非 Node.js 執行時(例如 CloudFlare Workers 或 Service Workers)成為可能。@vue/server-renderer

@vue/server-renderer

5. 效果範圍 API
3.2 引入了一個新的 Effect Scope API (effectScope、getCurrentScope、onScopeDispose等),用於直接控制反應性效果(計算和觀察者)的處理時間。它可以更輕鬆地在元件上下文之外利用 Vue 的響應式 API,並且還解鎖了元件內部的一些高階用例。


function effectScope(detached?: boolean): EffectScope
interface EffectScope {
run<T>(fn: () => T): T | undefined // undefined if scope is inactive
stop(): void
}


const scope = effectScope()
scope.run(() => {
const doubled = computed(() => counter.value * 2)

watch(doubled, () => console.log(doubled.value))

watchEffect(() => console.log('Count: ', doubled.value))
})

// to dispose all effects in the scope
scope.stop()


function getCurrentScope(): EffectScope | undefined

function onScopeDispose(fn: () => void): void
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
6. 一些屬性使用變更
(1)useContext API 被棄用
在原先,可以通過該 API 來獲取元件的上下文資訊,包含了 attrs 、slots 、emit、expose 等父子元件通訊資料和方法。
該 API 將在 3.2 版本之後刪除,context 裡面的資料,會用新的 useSlots 和 useAttrs API 來代替。

useAttrs:

// 匯入 useAttrs 元件
import { useAttrs } from "vue";

// 獲取 attrs
const attrs = useAttrs();

// attrs是個物件,和 props 一樣,需要通過 key 來得到對應的單個 attr
console.log(attrs.msg);
1
2
3
4
5
6
7
8
useSlots:

import { defineComponent, useSlots } from "vue";

const ChildTSX = defineComponent({
setup() {
// 獲取插槽資料
const slots = useSlots();

// 渲染元件
return () => (
<div>
// 渲染預設插槽
<p>{slots.default ? slots.default() : ""}</p>
// 渲染命名插槽
<p>{slots.msg ? slots.msg() : ""}</p>
</div>
);
},
});

export default ChildTSX;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
defineExpose:

原expose使用示例:

// 匯入 useContext 元件
import { useContext } from "vue";

// 啟用expose元件
const { expose } = useContext();

// 定義一個想提供給父元件拿到的資料
const msg: string = "Hello World!";

// 顯示暴露的資料,才可以在父元件拿到
expose({
msg,
});
1
2
3
4
5
6
7
8
9
10
11
12
13
3.2 版本後通過defineExpose暴露

// 匯入 defineExpose 元件
import { defineExpose } from "vue";

// 定義資料
const msg: string = "Hello World!";

// 暴露給父元件
defineExpose({
msg,
});
1
2
3
4
5
6
7
8
9
10
defineEmits:

// 匯入 defineEmits 元件
import { defineEmits } from "vue";

// 獲取 emit
const emit = defineEmits(["say-hi", "chang-name"]);

// 呼叫 emit 打招呼
emit("say-hi", "Hello!");

// 呼叫 emit 改名
emit("chang-name", "Tom");
1
2
3
4
5
6
7
8
9
10
11
新增withDefaults:

import { defineProps, withDefaults } from "vue";

withDefaults(
defineProps<{
size?: number;
labels?: string[];
}>(),
{
size: 3,
labels: () => ["default label"],
}
);
1
2
3
4
5
6
7
8
9
10
11
12
(2) 頂級 await 的支援
不必再配合 async 就可以直接使用 await 了,這種情況下,元件的 setup 會自動變成 async setup

<script setup lang="ts">
const post = await fetch(`/api/post/1`).then((r) => r.json());
</script>
1
2
3
它轉換成標準組件的寫法就是:

<script lang="ts">
import { defineComponent, withAsyncContext } from "vue";

export default defineComponent({
async setup() {
const post = await withAsyncContext(
fetch(`/api/post/1`).then((r) => r.json())
);

return {
post,
};
},
});
</script>