基础
多事件处理器
<!-- 这两个 one() 和 two() 将执行按钮点击事件 -->
<button @click="one($event), two($event)">
Submit
</button>
// ...
methods: {
one(event) {
// 第一个事件处理器逻辑...
},
two(event) {
// 第二个事件处理器逻辑...
}
}
深入组件
组件中使用v-model
v-bind.sync 已 改为 v-model.modelValue
默认情况下,组件上的 v-model 使用 modelValue 作为 prop 和 update:modelValue 作为事件。我们可以通过向 v-model 传递参数来修改这些名称:
在本例中,子组件将需要一个 title prop 并发出 update:title 要同步的事件:
<my-component v-model:title="bookTitle"></my-component>
app.component('my-component', {
props: {
title: String
},
emits: ['update:title'],
template: `
<input
type="text"
:value="title"
@input="$emit('update:title', $event.target.value)">
`
})
//对于所有不带参数的 v-model,请确保分别将 prop 和 event 命名更改为 modelValue 和 update:modelValue // 以前是 this.$emit('input', title)
<my-component v-model="bookTitle"></my-component>
app.component('my-component', {
props: {
modelValue: String
},
emits: ['update:modelValue'],
template: `
<input
type="text"
:value="title"
@input="this.$emit('update:modelValue', title) ">
`
})
多个 v-model 绑定
此用法可绑定多个modelValue
动态组件
我们之前曾经在一个多标签的界面中使用 is attribute 来切换不同的组件:
<component :is="currentTabComponent"></component>
currentTabComponent为组件名 点击切换显示不同组件
v-is 用于 DOM 内模板解析解决方案
<table>
<tr v-is="'blog-post-row'"></tr>
</table>
在 Vue 3.x 中 key 则应该被设置在 <template> 标签上。
v-if 与 v-for 的优先级对比
3.x 版本中 v-if 总是优先于 v-for 生效。
v-bind 合并行为
<!-- template -->
<div id="div-id" v-bind="{id: 'the-id', class: 'the-class'}">the-box</div>
在2.x 中 总是保留元素本身的attribute
<!-- result -->
<div id="div-id" class: 'the-class'></div>
3.x 语法
<!-- result -->
<div id="the-id" class: 'the-class'></div>
v-cloak
-
不需要表达式
-
用法:
这个指令保持在元素上直到关联组件实例结束编译。和 CSS 规则如
[v-cloak] { display: none }一起用时,这个指令可以隐藏未编译的 Mustache 标签直到组件实例准备完毕。 -
示例:
[v-cloak] { display: none; }<div v-cloak> {{ message }} </div>
不会显示,直到编译结束。
异步组件
2.x 语法
const AsyncComponent = () => ({
// 需要加载的组件 (应该是一个 `Promise` 对象)
component: import('./MyComponent.vue'),
// 异步组件加载时使用的组件
loading: LoadingComponent,
// 加载失败时使用的组件
error: ErrorComponent,
// 展示加载时组件的延时时间。默认值是 200 (毫秒)
delay: 200,
// 如果提供了超时时间且组件加载也超时了,
// 则使用加载失败时使用的组件。默认值是:`Infinity`
timeout: 3000
})
异步组件现在需要 defineAsyncComponent 方法来创建
3.x 语法
import { defineAsyncComponent } from 'vue'
import ErrorComponent from './components/ErrorComponent.vue'
import LoadingComponent from './components/LoadingComponent.vue'
// 不带选项的异步组件
const asyncModal = defineAsyncComponent(() => import('./Modal.vue'))
// 带选项的异步组件
const asyncModalWithOptions = defineAsyncComponent({
`loader: () => import('./Modal.vue')`,
delay: 200,
timeout: 3000,
errorComponent: ErrorComponent,
loadingComponent: LoadingComponent
})
对 2.x 所做的另一个更改是,component 选项现在被重命名为 loader,以便准确地传达不能直接提供组件定义的信息。
全局API
Vue.prototype 替换为 config.globalProperties
// 之前 - Vue 2
Vue.prototype.$http = () => {}
// 之后 - Vue 3
const app = createApp({})
app.config.globalProperties.$http = () => {}
渲染函数 API
定制内置元素(is)
对特殊的 is prop 的使用只严格限制在被保留的 <component> 标记中
<component :is="currentView"></component>
<tr is="vue:blog-post-row"></tr>
v-is
已在 3.1.0 中被废弃。请换用带有 vue 前缀的 is attribute。
getCurrentInstance
getCurrentInstance 支持访问内部组件实例。
WARNING
getCurrentInstance 只暴露给高阶使用场景,典型的比如在库中。强烈反对在应用的代码中使用 getCurrentInstance。请不要把它当作在组合式 API 中获取 this 的替代方案来使用。
import { getCurrentInstance } from 'vue'
const MyComponent = {
setup() {
const internalInstance = getCurrentInstance()
internalInstance.appContext.config.globalProperties // 访问 globalProperties
}
}
getCurrentInstance 只能在 setup 或生命周期钩子中调用。
如需在 setup 或生命周期钩子外使用,请先在
setup中调用getCurrentInstance()获取该实例然后再使用。
const MyComponent = {
setup() {
const internalInstance = getCurrentInstance() // 有效
const id = useComponentId() // 有效
const handleClick = () => {
getCurrentInstance() // 无效
useComponentId() // 无效
internalInstance // 有效
}
onMounted(() => {
getCurrentInstance() // 有效
})
return () =>
h(
'button',
{
onClick: handleClick
},
`uid: ${id}`
)
}
}
// 在组合式函数中调用也可以正常执行
function useComponentId() {
return getCurrentInstance().uid
}
expose 3.2+
-
类型:
Array<string> -
详细:
一个将暴露在公共组件实例上的 property 列表。
默认情况下,通过
$refs、$parent或$root访问到的公共实例与模板使用的组件内部实例是一样的。expose选项将限制公共实例可以访问的 property。由 Vue 自身定义的 property,比如
$el和$parent,将始终可以被公共实例访问,并不需要列出。 -
用法:
export default { // increment 将被暴露, // 但 count 只能被内部访问 expose: ['increment'], data() { return { count: 0 } }, methods: { increment() { this.count++ } } }
propsData
2.x 语法
在 2.x,我们可以在创建 Vue 实例的时候传入 prop:
const Comp = Vue.extend({
props: ['username'],
template: '<div>{{ username }}</div>'
})
new Comp({
propsData: {
username: 'Evan'
}
})
3.x 更新
propsData 选项已经被移除。如果你需要在实例创建时向根组件传入 prop,你应该使用 createApp 的第二个参数:
const app = createApp(
{
props: ['username'],
template: '<div>{{ username }}</div>'
},
{ username: 'Evan' }
)