模板语法
<div v-bind:id="dynamicId"></div>
<div :id="dynamicId"></div>
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div :id="`list-${id}`"></div>
<a :[attributeName]="url"> ... </a>
<a v-on:[eventName]="doSomething"> ... </a>
<a @[eventName]="doSomething">
完整的指令语法:
响应式基础
export default {
data() { // 创建新组件实例的时候调用,并将函数返回的对象用响应式系统进行包装,
return {//此对象的所有顶层属性都会被代理到组件实例 (`this`) 上。
count: 1
}
},
mounted() {
// `this` 指向当前组件实例
console.log(this.count) // => 1
},
methods: {//Vue自动为它中的方法绑定了永远指向组件实例的 `this`
increment() {//不要使用箭头函数,因为没有自己的 `this` 上下文
this.count++
nextTick(() => {//DOM 的更新并不是同步的
// 访问更新后的DOM
})
}
},
}
计算属性
一个计算属性仅会在其响应式依赖更新时才重新计算,否则会返回缓存结果。
computed: {
now() {//并不是一个响应式依赖,所以永远不会更新
return Date.now()
}
}
Class 与 Style 绑定
<div :class="{ active: isActive }"></div>
<div :class="[activeClass, errorClass]"></div>
<div :style="{ 'font-size': fontSize + 'px' }"></div>
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
<div :style="{ 'font-size': fontSize + 'px' }"></div>
条件渲染
v-show 不支持在 <template> 元素上使用,相当于切换display 的 CSS 属性。
v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要频繁切换,则使用 v-show 较好;如果在运行时绑定条件很少改变,则 v-if 会更合适。
同时使用 v-if 和 v-for 是不推荐的
列表渲染
<li v-for="({ key1, key2 }, index) in items"> // `key` attribute
{{ key1 }} {{key2}} {{ index }}
</li>
事件处理
<button @click="warn('Form cannot be submitted yet.', $event)">
传入一个特殊的原生 DOM 事件 `$event` 变量
</button>
<!-- 单击事件将停止传递 -->
<a @click.stop="doThis"></a>
<!-- 提交事件将不再重新加载页面 -->
<form @submit.prevent="onSubmit"></form>
<!-- 修饰语可以使用链式书写 -->
<a @click.stop.prevent="doThat"></a>
<!-- 也可以只有修饰符 -->
<form @submit.prevent></form>
<!-- 仅当 event.target 是元素本身时才会触发事件处理器 -->
<!-- 例如:事件处理器不来自子元素 -->
<div @click.self="doThat">...</div>
<input @keyup.enter="submit" />//`.tab` delete esc down space ctrl alt meta
<input @keyup.alt.enter="clear" />//Alt + Enter
生命周期
组件
app
.component('ComponentA', ComponentA)
.component('ComponentB', ComponentB)//链式调用 全局注册的组件
`<script setup>` 中,无需注册:
props
<script setup>
function Log(content) {
console.log(content)
}
const props = defineProps({
// 基础类型检查
// (给出 `null` 和 `undefined` 值则会跳过任何类型检查)
propA: Number,
propB: [String, Number],// 多种可能的类型
propC: { // 必传,且为 String 类型
type: String,
required: true
},
propD: { // Number 类型的默认值
type: Number,
default: 100
},
// 对象类型的默认值
propE: {
type: Object,
// 对象或数组的默认值
// 必须从一个工厂函数返回。
// 该函数接收组件所接收到的原始 prop 作为参数。
default(rawProps) {
return { message: 'hello' }
}
},
propF: { // 自定义类型校验函数
validator(value) { //校验失败后,Vue 会抛出一个控制台警告 (在开发模式下)。
return ['success', 'warning', 'danger'].includes(value)
}
},
// 函数类型的默认值
propG: {
type: Function,
// 不像对象或数组的默认,这不是一个工厂函数。这会是一个用来作为默认值的函数
default() {
return 'Default function'
}
}
})
Log(props)
</script>
事件
const emit = defineEmits(['submit1'])
function click() {
emit('submit1')
}
const emit2 = defineEmits({
// 没有校验
click: null,
// 校验 submit 事件
submit: ({ email, password }) => {
if (email && password) {
return true
} else {
console.warn('Invalid submit event payload!')
return false
}
}
})
// emit2('submit')
插槽
<div class="container">
<header>
<!-- 具名插槽 -->
<slot name="header"></slot>
</header>
<main>
<!-- 匿名插槽 默认插槽-->
<slot></slot>
</main>
</div>
<BaseLayout>
<!-- v-slot:name="slotProps" -->
<!-- 缩写 #name="slotProps" -->
<template #header="headerProps">
<h1>Here might be a page title</h1>
</template>
<!-- slotProps中是传过来的参数 -->
<template #default v-slot="slotProps">
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<!-- 动态插槽名 缩写为 -->
<template #[dynamicSlotName]>
...
</template>
</BaseLayout>
依赖注入
provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
app.provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
provide('read-only-count', readonly(count))
const message = inject('message')