Vue3 相對于 Vue2 值得關(guān)注的新特性
- Composition API 組合式 API
- 重新實現(xiàn)了數(shù)據(jù)響應(yīng)式原理(利用 ES6 的 proxy 代替了 ES5的 Object.defineProperty)
- 源碼使用 typescript 進行了重寫,擁有更好的類型推導(dǎo)
- Virtual DOM Rewrite 重寫虛擬DOM(渲染機制和優(yōu)化)
- Fragment 片段
- Teleport 瞬移術(shù)
- emits 觸發(fā)組件選項
Composition API 組合式 API
通過代碼來理解 Composition API 的作用和好處,以下是一個實例,實現(xiàn)了一個能實時顯示鼠標(biāo)坐標(biāo)位置的例子豌鹤。
<template>
<h1>Hello World</h1>
<div>
x: {{ position.x }}
</div>
<div>
y: {{ position.y }}
</div>
</template>
import { onMounted, onUnmounted, reactive } from 'vue'
export default {
name: 'App',
setup() {
const position = reactive({
x: 0,
y: 0
})
const update = e => {
position.x = e.pageX
position.y = e.pageY
}
onMounted(()=>{
window.addEventListener('mousemove', update)
})
onUnmounted(()=>{
window.removeEventListener('mousemove', update)
})
return {
position
}
}
}
重構(gòu)邏輯部分代碼
import { onMounted, onUnmounted, reactive } from 'vue'
function useMousePosition () {
const position = reactive({
x: 0,
y: 0
})
// 定義事件處理函數(shù)
const update = e => {
position.x = e.pageX
position.y = e.pageY
}
// 注冊事件
onMounted(()=>{
window.addEventListener('mousemove', update)
})
// 注銷事件
onUnmounted(()=>{
window.removeEventListener('mousemove', update)
})
return position
}
export default {
name: 'App',
setup() {
const position = useMousePosition()
return {
position
}
}
}
從上述的代碼中可以看出苟蹈,與 position 相關(guān)的變量根资、函數(shù)胎撇、生命周期狸捕、邏輯操作都被集中抽離到一個 useMousePosition 這個函數(shù)中热幔,邏輯更加耦合乐设,整套流程代碼查詢的時候也比較好定位,整個處理邏輯比較清晰绎巨,易于修改近尚。
setup 組件選項
為了開始使用組合式 API,我們首先需要一個可以實際使用它的地方场勤。在 Vue 組件中戈锻,我們將此位置稱為 setup
,setup 選項應(yīng)該是一個接受 props 和 context 的函數(shù)和媳。
props 是 setup 函數(shù)接收的第一個參數(shù)格遭,即組件的 props 屬性。context(上下文) 是 setup 函數(shù)接收的第二個參數(shù)留瞳,context 可以被解構(gòu)為 { attrs, slots, emit } 這三個參數(shù)拒迅。
新的 setup 組件選項在創(chuàng)建組件之前執(zhí)行,一旦 props 被解析她倘,并充當(dāng)合成 API 的入口點璧微。
WARNING:setup的執(zhí)行時機在:beforeCreate 之后 created之前。由于在執(zhí)行 setup 時尚未創(chuàng)建組件實例硬梁,因此在 setup 選項中沒有 this前硫。這意味著,除了 props 之外荧止,你將無法訪問組件中聲明的任何屬性——本地狀態(tài)屹电、計算屬性或方法。
reactive 和 ref
reactive 函數(shù)將傳遞的 json 對象或者數(shù)組包裝成了 proxy 對象罩息,使其具備響應(yīng)式
ref 函數(shù)可以處理基本數(shù)據(jù)類型的變量嗤详,包裝原始的基本值為一個對象个扰,使其變成響應(yīng)式數(shù)據(jù)瓷炮,通過 primaryValue.value 來訪問或更高該響應(yīng)式變量的值。
computed 和 watched 函數(shù)
computed 和 watched 可以單獨作為一個函數(shù)來使用
import { computed, ref } from '@vue/composition-api'
export default {
setup() {
const refCount = ref(1)
// 只讀
let computedCount = computed(() => refCount.value + 1)
console.log(computedCount)
return {
refCount,
computedCount
}
}
};
import { watch, ref } from '@vue/composition-api'
export default {
setup() {
const refCount = ref(100)
// 定義 watch递宅,只要 count 值變化娘香,就會觸發(fā) watch 回調(diào)
// 組件在第一次創(chuàng)建的時候執(zhí)行一次 watch
watch(() => console.log(refCount.value), { lazy: false})
setInterval(() => {
refCount.value += 2
}, 5000)
return {
refCount
}
}
};
生命周期鉤子注冊內(nèi)部 setup
為了使組合式 API 的特性與選項式 API 相比更加完整苍狰,我們還需要一種在 setup 中注冊生命周期鉤子的方法。這要歸功于從 Vue 導(dǎo)出的幾個新函數(shù)烘绽。組合式 API 上的生命周期鉤子與選項式 API 的名稱相同淋昭,但前綴為 on:即 mounted 看起來像 onMounted。
這些函數(shù)接受在組件調(diào)用鉤子時將執(zhí)行的回調(diào)安接。
例如代碼中的 onMounted() 和 onUnmouted() 鉤子函數(shù)翔忽,將在組件 mounted(加載) 和 unmouted(卸載) 的時候執(zhí)行事件回調(diào)。
Virtual DOM Rewrite 重寫虛擬DOM(渲染機制和優(yōu)化)
利用 patch flag 優(yōu)化靜態(tài)樹
https://www.pianshen.com/article/16291732261/
Fragment 片段
在 Vue 3 中盏檐,組件現(xiàn)在正式支持多根節(jié)點組件歇式,即片段!
在 2.x 中胡野,不支持多根組件材失,當(dāng)用戶意外創(chuàng)建多根組件時會發(fā)出警告,因此硫豆,為了修復(fù)此錯誤龙巨,許多組件被包裝在一個 <div> 中。
在 3.x 中熊响,組件現(xiàn)在可以有多個根節(jié)點旨别!但是,這確實要求開發(fā)者明確定義屬性應(yīng)該分布在哪里汗茄。
與單個根節(jié)點組件不同昼榛,具有多個根節(jié)點的組件不具有自動 attribute 回退行為。如果未顯式綁定 $attrs剔难,將發(fā)出運行時警告胆屿。
<custom-layout id="custom-layout" @click="changeValue"></custom-layout>
// 警告
app.component('custom-layout', {
template: `
<div class="one">one</div>
<div class="two">two</div>
<div class="three">three</div>
`
})
// 沒有警告,$attrs被傳遞到two元素
app.component('custom-layout', {
template: `
<div class="one">one</div>
<div class="two" v-bind="$attrs">two</div>
<div class="three">three</div>
`
})
Teleport 瞬移術(shù)
Teleport 提供了一種干凈的方法,允許我們控制在 DOM 中哪個父節(jié)點下呈現(xiàn) HTML偶宫,而不必求助于全局狀態(tài)或?qū)⑵洳鸱譃閮蓚€組件非迹。
以模態(tài)框舉例,可以在一個深度嵌套的 UI 組件中定義一個模態(tài)框纯趋,通過 Teleport To 把該模態(tài)框 append 到 body 的標(biāo)簽下憎兽。
Vue3 相對于 Vue2 的一些小改變
生命周期函數(shù)重命名
destroyed 生命周期選項被重命名為 unmounted
beforeDestroy 生命周期選項被重命名為 beforeUnmount
data 選項
在 3.x,data 選項已標(biāo)準(zhǔn)化為只接受返回 object 的 function吵冒。而不能像 2.x 中的那樣 data 可以是一個 object
<script>
import { createApp } from 'vue'
createApp({
data() {
return {
apiKey: 'a1b2c3'
}
}
}).mount('#app')
</script>
mixins 行為改變
此外纯命,當(dāng)來自組件的 data() 及其 mixin 或 extends 基類被合并時,現(xiàn)在將淺層次執(zhí)行合并痹栖。而不是深度合并亿汞。
const Mixin = {
data() {
return {
user: {
name: 'Jack',
id: 1
}
}
}
}
const CompA = {
mixins: [Mixin],
data() {
return {
user: {
id: 2
}
}
}
}
在 Vue 2.x中,生成的 $data 是:
{
user: {
id: 2,
name: 'Jack'
}
}
在 3.0 中揪阿,其結(jié)果將會是:
{
user: {
id: 2
}
}
Vue3 相對于 Vue2 不兼容的變化
過濾器 filters
從 Vue 3.0 開始疗我,過濾器已刪除咆畏,不再支持。