新特性(區(qū)別)
1、片段:vue3.0中template支持多個根標(biāo)簽;(vue2只能單個)
2、組合式API--setup:(2.0的稱為選項(xiàng)式API)
(1)在組件創(chuàng)建前執(zhí)行,且只能接受(訪問)props和context的函數(shù);
(2)返回的內(nèi)容將暴露給組件其他部分(計(jì)算屬性、方法、生命周期等)以及組件模板;
(3)在 setup 中注冊生命周期鉤子的方法。這要?dú)w功于從 Vue 導(dǎo)出的幾個新函數(shù)。組合式 API 上的生命周期鉤子與選項(xiàng)式 API 的名稱相同,但前綴為 on:即 mounted 會看起來像 onMounted。
3、ref函數(shù):
(1)作用:使任何響應(yīng)式變量在任何地方起作用;(通過對象的引用地址來實(shí)現(xiàn)響應(yīng))
(2)接受參數(shù),并將其包裹在一個帶有 value property 的對象中返回;【eg:const test = ref(1) // test.value === 1】
(3)toRefs函數(shù):創(chuàng)建對props(猜測可能對對象某個屬性也行)的某個屬性響應(yīng)式引用;
4、watch響應(yīng)式更改
** 接收三個參數(shù):
- 一個我們想要偵聽的響應(yīng)式引用或 getter 函數(shù);
- 一個回調(diào);
- 可選的配置選項(xiàng);
import { ref, watch } from 'vue'
const counter = ref(0)
watch(counter, (newValue, oldValue) => {
console.log('The new counter value is: ' + counter.value)
})
5、獨(dú)立的computed屬性
import { ref, computed } from 'vue'
const counter = ref(0)
const twiceTheCounter = computed(() => counter.value * 2)
counter.value++
console.log(counter.value) // 1
console.log(twiceTheCounter.value) // 2 --注意這邊是`.value`
6、Teleport(傳送)
(1)作用:可指定包裹的html結(jié)構(gòu)渲染在哪個DOM下;
(2)代碼展示:
<button @click="modalOpen = true">
Open full screen modal! (With teleport!)
</button>
<teleport to="body"> // 渲染到body下面
<div v-if="modalOpen" class="modal">
<div>
I'm a teleported modal!
(My parent is "body")
<button @click="modalOpen = false">
Close
</button>
</div>
</div>
</teleport>
(3)與 Vue components 一起使用
如果 <teleport> 包含 Vue 組件,則它仍將是 <teleport> 父組件的邏輯子組件:
const app = Vue.createApp({
template: `
<h1>Root instance</h1>
<parent-component />
`
})
app.component('parent-component', {
template: `
<h2>This is a parent component</h2>
<teleport to="#endofbody">
<child-component name="John" />
</teleport>
`
})
app.component('child-component', {
props: ['name'],
template: `
<div>Hello, {{ name }}</div>
`
})
在這種情況下,即使在不同的地方渲染 child-component,它仍將是 parent-component 的子級,并將從中接收 name prop。
7、定義觸發(fā)事件:可直接在組件通過emits選項(xiàng)定義
(1)emits: ['inFocus', 'subimit'] 或?qū)ο笠残?,可像props一樣校驗(yàn)傳遞參數(shù);
(2)代碼示例
app.component('custom-form', {
emits: {
// 沒有驗(yàn)證
click: null,
// 驗(yàn)證submit 事件
submit: ({ email, password }) => {
if (email && password) {
return true
} else {
console.warn('Invalid submit event payload!')
return false
}
}
},
methods: {
submitForm() {
this.$emit('submit', { email, password })
}
}
})
8、多個v-model綁定
<user-name
v-model:first-name="firstName"
v-model:last-name="lastName"
></user-name>
app.component('user-name', {
props: {
firstName: String,
lastName: String
},
emits: ['update:firstName', 'update:lastName'],
template: `
<input
type="text"
:value="firstName"
@input="$emit('update:firstName', $event.target.value)">
<input
type="text"
:value="lastName"
@input="$emit('update:lastName', $event.target.value)">
`
})
9、v-model支持自定義修飾符,通過props中modelModifiers訪問;
10、新的全局API:createApp
(1)被創(chuàng)建原因:2.0的全局配置會影響多個app實(shí)例:
// 這會影響兩個根實(shí)例
Vue.mixin({
/* ... */
})
const app1 = new Vue({ el: '#app-1' })
const app2 = new Vue({ el: '#app-2' }
(2)使用:
import { createApp } from 'vue'
import MyApp from './MyApp.vue'
const app = createApp(MyApp)
app.mount('#app')
(3)Vue.prototype 替換為 config.globalProperties
// 之前 - Vue 2
Vue.prototype.$http = () => {}
// 之后 - Vue 3
const app = createApp({})
app.config.globalProperties.$http = () => {}
(4)由于 use 全局 API 在 Vue 3 中不再使用,此方法將停止工作并停止調(diào)用 Vue.use() 現(xiàn)在將觸發(fā)警告,于是,開發(fā)者必須在應(yīng)用程序?qū)嵗巷@式指定使用此插件:
const app = createApp(MyApp)
app.use(VueRouter)
11、v-model默認(rèn)prop由value改為modelValue,觸發(fā)事件由$emit('input', newValue)改為$emit.('update:modelValue', newValue)
12、v-for變更
(1)可遍歷對象:P1--value p2--key p3--index;
(2)可接受整數(shù)
<div id="range" class="demo">
<span v-for="n in 10" :key="n">{{ n }} </span>
</div>
// 輸出:12345678910
13、v-if和v-for優(yōu)先級變更:3.x中v-if優(yōu)先級更高;(盡量避免同時使用兩者)
14、v-bind合并行為變更
// 2.x版本
<!-- template -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- result -->
<div id="red"></div>
// 3.x版本:以順序?yàn)橹?,往前覆蓋
<!-- template -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- result -->
<div id="blue"></div>
<!-- template -->
<div v-bind="{ id: 'blue' }" id="red"></div>
<!-- result -->
<div id="red"></div>
15、移除v-on.native修飾符:3.x新增emits選項(xiàng)定義自定義事件,未定義的默認(rèn)為原生事件;(除非在子組件的選項(xiàng)中設(shè)置了 inheritAttrs: false)
16、v-for 中的 Ref 數(shù)組
<div v-for="item in list" :ref="setItemRef"></div>
import { onBeforeUpdate, onUpdated } from 'vue'
export default {
setup() {
let itemRefs = []
const setItemRef = el => {
if (el) {
itemRefs.push(el)
}
}
onBeforeUpdate(() => {
itemRefs = []
})
onUpdated(() => {
console.log(itemRefs)
})
return {
setItemRef
}
}
}
17、異步組件:* [異步組件現(xiàn)在需要 defineAsyncComponent 方法來創(chuàng)建]
// 2.x 版本
const oldAsyncComponent = (resolve, reject) => {
/* ... */
}
// 3.x 版本: loader 函數(shù)不再接收 resolve 和 reject 參數(shù),且必須始終返回 Promise
const asyncComponent = defineAsyncComponent(
() =>
new Promise((resolve, reject) => {
/* ... */
})
)
18、渲染函數(shù)變更:h(它是 createElement 的傳統(tǒng)別名))現(xiàn)在是全局導(dǎo)入,不是render中作為參數(shù)傳入;
// Vue 2 渲染函數(shù)示例
export default {
render(h) {
return h('div')
}
}
// Vue 3 渲染函數(shù)示例
import { h } from 'vue'
export default {
render() {
return h('div')
}
}
19、統(tǒng)一普通插槽和作用域插槽;
20、自定義元素方式改變;(還有is和v-is)
// 2.x版本
// 這將使Vue忽略在Vue外部定義的自定義元素
// (例如:使用 Web Components API)
Vue.config.ignoredElements = ['plastic-button']
// 3.x版本
// webpack 中的配置
rules: [
{
test: /\.vue$/,
use: 'vue-loader',
options: {
compilerOptions: {
isCustomElement: tag => tag === 'plastic-button'
}
}
}
// ...
]
// 如果使用動態(tài)模板編譯,請通過 app.config.isCustomElement 傳遞:
const app = Vue.createApp({})
app.config.isCustomElement = tag => tag === 'plastic-button'
21、destroyed 生命周期選項(xiàng)被重命名為 unmounted;beforeDestroy 生命周期選項(xiàng)被重命名為 beforeUnmount;
22、default prop 工廠函數(shù)不再可以訪問 this 上下文;
23、* 自定義指令 API 已更改為與組件生命周期一致;
24、* data 選項(xiàng)應(yīng)始終被聲明為一個函數(shù)
- 來自 mixin 的
data選項(xiàng)現(xiàn)在為淺合并 - Attribute 強(qiáng)制策略已更改
- 一些過渡 class 被重命名
<TransitionGroup>不再默認(rèn)渲染包裹元素- 當(dāng)偵聽一個數(shù)組時,只有當(dāng)數(shù)組被替換時,回調(diào)才會觸發(fā),如果需要在變更時觸發(fā),則需要指定
deep選項(xiàng) - 沒有特殊指令的標(biāo)記 (
v-if/else-if/else、v-for或v-slot) 的<template>現(xiàn)在被視為普通元素,并將生成原生的<template>元素,而不是渲染其內(nèi)部內(nèi)容。 - 在 Vue 2.x 中,應(yīng)用根容器的
outerHTML將替換為根組件模板 (如果根組件沒有模板/渲染選項(xiàng),則最終編譯為模板)。Vue 3.x 現(xiàn)在使用應(yīng)用容器的innerHTML,這意味著容器本身不再被視為模板的一部分。