跳到主要内容

Vue 知识速查表

本页面汇总了 Vue 3 开发中最常用的语法和知识点,方便快速查阅。

基础概念

创建应用

import { createApp } from 'vue'

const app = createApp({
data() {
return { message: 'Hello Vue!' }
}
})

app.mount('#app')

单文件组件 (.vue)

<script setup>
import { ref, computed } from 'vue'

// 逻辑代码
const count = ref(0)
</script>

<template>
<!-- 模板 -->
<p>{{ count }}</p>
</template>

<style scoped>
/* 样式 */
</style>

响应式 API

ref 和 reactive

import { ref, reactive } from 'vue'

// ref - 基本类型
const count = ref(0)
count.value++

// reactive - 对象
const state = reactive({
count: 0,
name: '张三'
})
state.count++

computed

import { computed } from 'vue'

const count = ref(1)
const doubled = computed(() => count.value * 2)

// 可写计算属性
const fullName = computed({
get: () => firstName.value + lastName.value,
set: (value) => { /* ... */ }
})

watch

import { watch } from 'vue'

watch(count, (newValue, oldValue) => {
console.log(`${oldValue} -> ${newValue}`)
})

// 深度监听
watch(state, (newValue) => { /* ... */ }, { deep: true })

// 立即执行
watch(count, (newValue) => { /* ... */ }, { immediate: true })

// 监听多个
watch([count1, count2], ([new1, new2]) => { /* ... */ })

watchEffect

import { watchEffect } from 'vue'

// 自动追踪依赖
watchEffect(() => {
console.log(count.value)
console.log(name.value)
})

模板语法

插值

<!-- 文本 -->
{{ message }}

<!-- 原始 HTML -->
<span v-html="rawHtml"></span>

<!-- JavaScript 表达式 -->
{{ message.split('').reverse().join('') }}

指令

<!-- 绑定属性 -->
<img :src="imageSrc" />
<div :class="{ active: isActive }"></div>

<!-- 绑定事件 -->
<button @click="handleClick">点击</button>
<form @submit.prevent="handleSubmit"></form>

<!-- 双向绑定 -->
<input v-model="message" />
<input v-model.number="age" />
<input v-model.trim="username" />

<!-- 条件渲染 -->
<div v-if="show">显示</div>
<div v-else>隐藏</div>
<div v-show="show">v-show</div>

<!-- 列表渲染 -->
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
<li v-for="(item, index) in items">{{ index }}. {{ item }}</li>

<!-- 绑定样式 -->
<div :style="{ color: textColor, fontSize: fontSize + 'px' }"></div>

事件修饰符

@click.stop="handleClick"      <!-- 阻止冒泡 -->
@click.prevent="handleSubmit" <!-- 阻止默认行为 -->
@click.self="handleClick" <!-- 仅自身触发 -->
@click.once="handleClick" <!-- 只触发一次 -->
@click.ctrl="handleClick" <!-- Ctrl 键 -->

组件

Props

<!-- 父组件 -->
<ChildComponent
:title="title"
:count="count"
required-prop="必填"
:optional-prop="optional"
/>

<!-- 子组件 -->
<script setup>
defineProps({
title: String,
count: {
type: Number,
required: true,
default: 0
},
items: {
type: Array,
default: () => []
}
})
</script>

Emits

<!-- 子组件 -->
<script setup>
const emit = defineEmits(['update', 'delete'])

emit('update', newValue)
emit('delete', id)
</script>

<!-- 父组件 -->
<ChildComponent
@update="handleUpdate"
@delete="handleDelete"
/>

v-model

<!-- 组件支持 v-model -->
<script setup>
defineProps({ modelValue: String })
defineEmits(['update:modelValue'])
</script>

<!-- 使用 -->
<Input v-model="text" />

<!-- 多个 v-model -->
<Input v-model:name="name" v-model:email="email" />

插槽

<!-- 父组件 -->
<Layout>
<template #header>页眉</template>
<template #default>主内容</template>
<template #footer>页脚</template>
</Layout>

<!-- 子组件 -->
<slot name="header">默认内容</slot>
<slot>默认插槽</slot>

<!-- 作用域插槽 -->
<slot :item="item" :index="index" />

生命周期

组合式 API 钩子

选项式 API组合式 API
beforeCreate不需要
created不需要
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted
import { onMounted, onUnmounted } from 'vue'

onMounted(() => {
console.log('mounted')
})

onUnmounted(() => {
console.log('unmounted')
})

路由

Vue Router 4

// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from './views/Home.vue'
import About from './views/About.vue'

const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/user/:id', component: User }
]

const router = createRouter({
history: createWebHistory(),
routes
})

export default router
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

createApp(App).use(router).mount('#app')
<!-- 路由视图 -->
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
<router-view />

<!-- 编程式导航 -->
<script setup>
import { useRouter } from 'vue-router'

const router = useRouter()
router.push('/home')
router.back()
</script>

状态管理 (Pinia)

// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
getters: {
doubled: (state) => state.count * 2
},
actions: {
increment() {
this.count++
}
}
})
// 使用
import { useCounterStore } from './stores/counter'

const store = useCounterStore()
store.increment()
console.log(store.count)
console.log(store.doubled)

常用工具函数

toRef / toRefs

import { reactive, toRef, toRefs } from 'vue'

const state = reactive({ count: 0, name: '张三' })

// toRef - 保持响应式连接
const count = toRef(state, 'count')

// toRefs - 转换为普通对象
const { count, name } = toRefs(state)

isRef

import { isRef } from 'vue'

isRef(count) // true / false

常用 CSS

scoped

<style scoped>
/* 只作用于当前组件 */
.button { /* ... */ }
</style>

CSS Modules

<style module>
/* 访问 $style.button */
</style>

深度选择器

<style scoped>
/* 穿透子组件 */
:deep(.child-class) { /* ... */ }

/* 穿透伪类 */
:hover { /* ... */ }
</style>

常见问题

访问 DOM

const el = ref(null)

onMounted(() => {
console.log(el.value)
})
</script>

<template>
<div ref="el"></div>
</template>

组件暴露方法

<!-- Child.vue -->
<script setup>
defineExpose({
method: () => console.log('exposed')
})
</script>

<!-- Parent.vue -->
<Child ref="child" />
<script setup>
child.value?.method()
</script>

异步组件

import { defineAsyncComponent } from 'vue'

const AsyncComponent = defineAsyncComponent(() =>
import('./HeavyComponent.vue')
)

快捷命令

# 创建项目
npm create vue@latest

# 安装依赖
npm install

# 开发服务器
npm run dev

# 构建生产版本
npm run build

# 预览构建结果
npm run preview

# 代码检查
npm run lint

参考资源