Vue 3 核心语法速查

一、基础使用

1. 创建应用

```javascript

// main.js

import { createApp } from 'vue'

import App from './App.vue'

const app = createApp(App)

app.mount('#app')

```

2. 模板语法

```vue

<template>

<!-- 插值 -->

<p>{{ message }}</p>

<!-- 原始HTML -->

<div v-html="rawHtml"></div>

<!-- 属性绑定 -->

<div :id="dynamicId"></div>

<button :disabled="isDisabled">按钮</button>

<!-- 简写 -->

<div :class="{ active: isActive }"></div>

<div :style="{ color: activeColor }"></div>

<!-- 事件绑定 -->

<button @click="handleClick">点击</button>

<input @keyup.enter="submit">

<!-- 双向绑定 -->

<input v-model="text">

<input v-model.number="age" type="number">

<input v-model.trim="text">

<!-- 条件渲染 -->

<div v-if="type === 'A'">A</div>

<div v-else-if="type === 'B'">B</div>

<div v-else>C</div>

<!-- 显示/隐藏 -->

<div v-show="isVisible">显示/隐藏</div>

<!-- 列表渲染 -->

<li v-for="(item, index) in items" :key="item.id">

{{ index }} - {{ item.name }}

</li>

<!-- 遍历对象 -->

<div v-for="(value, key) in object" :key="key">

{{ key }}: {{ value }}

</div>

</template>

```

3. 组件定义

```vue

<script setup>

// Composition API (推荐)

import { ref, reactive, computed, watch } from 'vue'

// 响应式数据

const count = ref(0)

const state = reactive({

name: 'Vue 3',

version: '3.0'

})

// 计算属性

const fullName = computed(() => {

return `{state.name} {state.version}`

})

// 方法

const increment = () => {

count.value++

}

// 侦听器

watch(count, (newValue, oldValue) => {

console.log(`count变化: {oldValue} -\> {newValue}`)

})

// 立即执行的侦听器

watch(

() => state.name,

(newValue) => {

console.log(`name变化: ${newValue}`)

},

{ immediate: true }

)

// 侦听多个数据源

watch([count, () => state.name], ([newCount, newName]) => {

console.log(newCount, newName)

})

// 生命周期

import { onMounted, onUpdated, onUnmounted } from 'vue'

onMounted(() => {

console.log('组件已挂载')

})

onUnmounted(() => {

console.log('组件已卸载')

})

</script>

<template>

<button @click="increment">{{ count }}</button>

<p>{{ fullName }}</p>

</template>

```

二、组件通信

1. Props 和 Emits

```vue

<!-- 子组件 Child.vue -->

<script setup>

// 定义props

const props = defineProps({

title: String,

count: {

type: Number,

default: 0,

required: true

}

})

// 定义emits

const emit = defineEmits(['update:count', 'customEvent'])

const handleClick = () => {

emit('update:count', props.count + 1)

emit('customEvent', 'data')

}

</script>

<template>

<h2>{{ title }}</h2>

<p>Count: {{ count }}</p>

<button @click="handleClick">增加</button>

</template>

<!-- 父组件 Parent.vue -->

<script setup>

import { ref } from 'vue'

import Child from './Child.vue'

const count = ref(0)

const handleCustomEvent = (data) => {

console.log('收到数据:', data)

}

</script>

<template>

<Child

title="子组件"

:count="count"

@update:count="count = $event"

@custom-event="handleCustomEvent"

/>

</template>

```

2. 组件引用和Expose

```vue

<!-- 子组件 MyInput.vue -->

<script setup>

import { ref, defineExpose } from 'vue'

const inputRef = ref(null)

const value = ref('')

const focus = () => {

inputRef.value?.focus()

}

// 暴露给父组件的方法

defineExpose({

focus,

value

})

</script>

<template>

<input ref="inputRef" v-model="value">

</template>

<!-- 父组件 -->

<script setup>

import { ref } from 'vue'

import MyInput from './MyInput.vue'

const inputRef = ref()

const handleFocus = () => {

inputRef.value.focus()

console.log(inputRef.value.value)

}

</script>

<template>

<MyInput ref="inputRef" />

<button @click="handleFocus">聚焦</button>

</template>

```

3. Provide/Inject

```vue

<!-- 祖先组件 -->

<script setup>

import { provide, ref } from 'vue'

const theme = ref('dark')

provide('theme', theme)

provide('changeTheme', (newTheme) => {

theme.value = newTheme

})

</script>

<!-- 后代组件 -->

<script setup>

import { inject } from 'vue'

const theme = inject('theme')

const changeTheme = inject('changeTheme')

</script>

```

三、响应式系统

1. ref 和 reactive

```javascript

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

// ref: 用于基本类型

const count = ref(0)

console.log(count.value) // 访问值

// reactive: 用于对象

const state = reactive({

count: 0,

name: 'Vue'

})

// 解构响应式对象

const { count, name } = toRefs(state)

// 现在 count 和 name 都是 ref

// 只读响应式对象

import { readonly } from 'vue'

const readOnlyState = readonly(state)

// 浅层响应式

import { shallowRef, shallowReactive } from 'vue'

const shallow = shallowReactive({ nested: { count: 0 } })

// nested 的变化不会触发更新

```

2. 响应式工具

```javascript

import { isRef, unref, toRef, markRaw } from 'vue'

// 检查是否是 ref

isRef(count) // true

// 获取值(如果是ref则.value,否则返回本身)

const value = unref(maybeRef)

// 将响应式对象属性转为 ref

const countRef = toRef(state, 'count')

// 标记为不可响应式

const rawObject = markRaw({ nested: {} })

```

四、计算属性和侦听器

1. 计算属性

```javascript

import { computed } from 'vue'

// 只读计算属性

const fullName = computed(() => {

return `{firstName.value} {lastName.value}`

})

// 可写计算属性

const writableFullName = computed({

get() {

return `{firstName.value} {lastName.value}`

},

set(newValue) {

const [first, last] = newValue.split(' ')

firstName.value = first

lastName.value = last

}

})

```

2. 侦听器

```javascript

import { watch, watchEffect } from 'vue'

// 基础侦听

watch(count, (newValue, oldValue) => {

// 当count变化时执行

})

// 侦听多个源

watch([count, name], ([newCount, newName], [oldCount, oldName]) => {

// 当任意一个变化时执行

})

// 深度侦听对象

watch(

() => state.user,

(newUser) => {

console.log(newUser)

},

{ deep: true }

)

// 立即执行并清理副作用

watchEffect((onCleanup) => {

console.log(count.value)

// 清理函数

onCleanup(() => {

console.log('清理')

})

})

// 控制侦听时机

watch(

count,

() => {

console.log('count changed')

},

{ flush: 'post' } // 或 'pre'、'sync'

)

```

五、生命周期

```javascript

import {

onBeforeMount,

onMounted,

onBeforeUpdate,

onUpdated,

onBeforeUnmount,

onUnmounted,

onErrorCaptured,

onActivated,

onDeactivated

} from 'vue'

onBeforeMount(() => {

// 挂载前

})

onMounted(() => {

// 挂载后 - 可以访问DOM

})

onBeforeUpdate(() => {

// 更新前

})

onUpdated(() => {

// 更新后

})

onBeforeUnmount(() => {

// 卸载前

})

onUnmounted(() => {

// 卸载后 - 清理工作

})

onErrorCaptured((err, instance, info) => {

// 捕获子组件错误

return false // 阻止错误继续向上传播

})

// KeepAlive组件特有

onActivated(() => {

// 激活时

})

onDeactivated(() => {

// 停用时

})

```

六、自定义指令

```javascript

// 全局指令

app.directive('focus', {

mounted(el) {

el.focus()

}

})

// 局部指令

<script setup>

const vMyDirective = {

mounted(el, binding) {

// binding.value - 指令的值

// binding.oldValue - 之前的值(仅在beforeUpdate和updated中可用)

// binding.arg - 传给指令的参数

// binding.modifiers - 修饰符对象

},

updated(el, binding) {

// 更新时调用

},

beforeUnmount(el) {

// 卸载前清理

}

}

</script>

<template>

<input v-my-directive:arg.modifier="value">

</template>

```

七、内置组件

1. Transition

```vue

<template>

<button @click="show = !show">切换</button>

<Transition name="fade">

<p v-if="show">Hello</p>

</Transition>

<!-- 使用CSS -->

<style>

.fade-enter-active,

.fade-leave-active {

transition: opacity 0.5s;

}

.fade-enter-from,

.fade-leave-to {

opacity: 0;

}

</style>

</template>

```

2. TransitionGroup

```vue

<template>

<TransitionGroup name="list" tag="ul">

<li v-for="item in items" :key="item.id">

{{ item.text }}

</li>

</TransitionGroup>

</template>

```

3. KeepAlive

```vue

<template>

<KeepAlive :include="['ComponentA']" :exclude="['ComponentB']" :max="10">

<component :is="currentComponent" />

</KeepAlive>

</template>

```

4. Teleport

```vue

<template>

<button @click="modalOpen = true">打开模态框</button>

<Teleport to="body">

<div v-if="modalOpen" class="modal">

<p>模态框内容</p>

<button @click="modalOpen = false">关闭</button>

</div>

</Teleport>

</template>

```

5. Suspense

```vue

<!-- 父组件 -->

<template>

<Suspense>

<template #default>

<AsyncComponent />

</template>

<template #fallback>

<div>加载中...</div>

</template>

</Suspense>

</template>

<!-- 异步组件 -->

<script setup>

const { data } = await fetch('/api/data').then(r => r.json())

</script>

```

八、组合式函数

```javascript

// useMouse.js

import { ref, onMounted, onUnmounted } from 'vue'

export function useMouse() {

const x = ref(0)

const y = ref(0)

function update(event) {

x.value = event.pageX

y.value = event.pageY

}

onMounted(() => window.addEventListener('mousemove', update))

onUnmounted(() => window.removeEventListener('mousemove', update))

return { x, y }

}

// 在组件中使用

<script setup>

import { useMouse } from './useMouse'

const { x, y } = useMouse()

</script>

<template>

<p>鼠标位置: {{ x }}, {{ y }}</p>

</template>

```

九、TypeScript支持

```vue

<script setup lang="ts">

// 类型定义

interface User {

id: number

name: string

age?: number

}

// 带类型的ref

import { ref } from 'vue'

const user = ref<User>({

id: 1,

name: '张三'

})

// 带类型的props

const props = defineProps<{

title: string

count?: number

users: User[]

}>()

// 带类型的emits

const emit = defineEmits<{

(e: 'update:count', value: number): void

(e: 'select', user: User): void

}>()

// 带类型的computed

import { computed } from 'vue'

const userName = computed<string>(() => user.value.name)

// 带类型的provide/inject

import { provide, inject } from 'vue'

const key = Symbol() as InjectionKey<string>

provide(key, 'value')

const value = inject(key)

</script>

```

十、状态管理(Pinia)

```javascript

// store/user.js

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {

state: () => ({

name: '张三',

age: 25,

token: null

}),

getters: {

// 类似计算属性

isAdult: (state) => state.age >= 18,

// 使用其他getter

greeting: (state) => {

return `Hello, ${state.name}`

}

},

actions: {

// 同步操作

updateName(newName) {

this.name = newName

},

// 异步操作

async login(credentials) {

const response = await api.login(credentials)

this.token = response.token

}

}

})

// 在组件中使用

<script setup>

import { useUserStore } from '@/stores/user'

import { storeToRefs } from 'pinia'

const userStore = useUserStore()

// 直接修改状态

userStore.name = '李四'

// 使用action

userStore.updateName('王五')

// 使用getter

console.log(userStore.isAdult)

// 解构并保持响应式

const { name, age } = storeToRefs(userStore)

</script>

```

十一、路由(Vue Router 4)

```javascript

// router/index.js

import { createRouter, createWebHistory } from 'vue-router'

const routes = [

{

path: '/',

name: 'Home',

component: () => import('../views/Home.vue')

},

{

path: '/user/:id',

name: 'User',

component: () => import('../views/User.vue'),

props: true, // 将params作为props传递

meta: { requiresAuth: true }

},

{

path: '/about',

component: () => import('../views/About.vue'),

children: [

{

path: 'info',

component: () => import('../views/AboutInfo.vue')

}

]

}

]

const router = createRouter({

history: createWebHistory(),

routes

})

// 导航守卫

router.beforeEach((to, from, next) => {

if (to.meta.requiresAuth && !isAuthenticated) {

next('/login')

} else {

next()

}

})

```

```vue

<!-- 在组件中使用 -->

<script setup>

import { useRoute, useRouter } from 'vue-router'

const route = useRoute()

const router = useRouter()

// 获取路由参数

console.log(route.params.id)

console.log(route.query.search)

// 导航

router.push('/home')

router.push({ name: 'User', params: { id: 1 } })

router.replace('/login')

router.go(-1)

// 编程式导航

const navigate = () => {

router.push({

path: '/user',

query: { search: 'vue' }

})

}

</script>

<template>

<!-- 路由链接 -->

<router-link to="/">首页</router-link>

<router-link :to="{ name: 'User', params: { id: 1 } }">

用户

</router-link>

<!-- 路由出口 -->

<router-view />

<router-view name="sidebar" /> <!-- 命名视图 -->

</template>

```

十二、实用技巧

1. 动态组件

```vue

<script setup>

import { shallowRef } from 'vue'

import Home from './Home.vue'

import About from './About.vue'

const components = {

Home,

About

}

const currentComponent = shallowRef(Home)

</script>

<template>

<component :is="currentComponent" />

<component :is="components['Home']" />

</template>

```

2. 自定义v-model

```vue

<!-- 子组件 -->

<script setup>

const props = defineProps(['modelValue'])

const emit = defineEmits(['update:modelValue'])

const updateValue = (event) => {

emit('update:modelValue', event.target.value)

}

</script>

<template>

<input :value="modelValue" @input="updateValue">

</template>

<!-- 父组件 -->

<template>

<CustomInput v-model="text" />

<!-- 相当于 -->

<CustomInput

:modelValue="text"

@update:modelValue="text = $event"

/>

</template>

```

3. 属性透传

```vue

<!-- 父组件 -->

<template>

<MyButton class="large" @click="handleClick">

按钮

</MyButton>

</template>

<!-- 子组件 MyButton.vue -->

<template>

<button v-bind="$attrs" class="btn">

<slot />

</button>

</template>

<script>

// 禁用属性继承

export default {

inheritAttrs: false

}

</script>

```

4. 性能优化

```javascript

// 1. 使用shallowRef/shallowReactive

import { shallowRef } from 'vue'

const largeObject = shallowRef({ /* 大数据 */ })

// 2. 使用v-once

<template>

<div v-once>{{ staticContent }}</div>

</template>

// 3. 使用v-memo (Vue 3.2+)

<div v-memo="[valueA, valueB]">

<!-- 仅当valueA或valueB变化时更新 -->

</div>

// 4. 使用异步组件

import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() =>

import('./components/AsyncComponent.vue')

)

```


**快速记忆要点:**

  1. **组合式API是核心** - `ref()`, `reactive()`, `computed()`, `watch()`

  2. **`<script setup>` 简化代码** - 自动导出,无需`return`

  3. **TypeScript友好** - 完整的类型支持

  4. **响应式系统改进** - 更精确的依赖追踪

  5. **更小的包体积** - Tree-shaking支持更好

  6. **更好的性能** - 更快的渲染速度和内存使用

  7. **新的内置组件** - `Teleport`, `Suspense`

  8. **多个根节点** - Fragment支持

相关推荐
雨季6665 小时前
Flutter 三端应用实战:OpenHarmony “安全文本溢出处理调节器”
开发语言·前端·安全·flutter·交互
雨季6666 小时前
Flutter 三端应用实战:OpenHarmony “极简安全文本对齐调节器”
开发语言·前端·javascript·安全·flutter·交互
肖。35487870946 小时前
html选择页最简模板源码,用于集合很多网页!游戏大全数字导航页面,数字选择页制作灵感,已经压缩到最小,现代,讲解。
android·java·javascript·css·html
qq_177767376 小时前
React Native鸿蒙跨平台完成动漫应用实现本地数据持久化、收藏管理、观看历史记录、标签页切换
javascript·react native·react.js·ecmascript·harmonyos
木子啊6 小时前
Uni-app跨页面通信三剑客
前端·uni-app·传参
tao3556677 小时前
【用AI学前端】准备工作
前端·人工智能
利刃大大8 小时前
【Vue】自定义指令directives && 指令钩子 && IntersectionObserver
前端·javascript·vue.js
共享家952714 小时前
搭建 AI 聊天机器人:”我的人生我做主“
前端·javascript·css·python·pycharm·html·状态模式
Halo_tjn15 小时前
基于封装的专项 知识点
java·前端·python·算法