1. Vue 3 核心概念
1.1 Vue 是什么
Vue 是一个渐进式 JavaScript 框架,用于构建用户界面。特点:
- 渐进式:可以逐步采用,从简单到复杂
- 声明式渲染:使用模板语法声明式地描述界面
- 组件化:构建可复用的组件
- 响应式:数据变化自动更新视图
1.2 Vue 3 新特性
javascript
// 1. Composition API(组合式API)
// 2. Teleport(传送门)
// 3. Fragments(片段)
// 4. Emits Option(自定义事件选项)
// 5. 更好的 TypeScript 支持
// 6. 更小的体积(Tree-shaking 优化)
// 7. 更快的性能(Proxy 取代 defineProperty)
2. 响应式系统
2.1 响应式基础
vue
<script setup>
import { ref, reactive, toRefs } from 'vue'
// ref: 用于基本类型
const count = ref(0) // 创建响应式数据
console.log(count.value) // 访问值
count.value++ // 修改值
// reactive: 用于对象
const state = reactive({
name: 'Vue 3',
version: '3.3'
})
console.log(state.name) // 直接访问
state.version = '3.4' // 直接修改
// toRefs: 将响应式对象转换为 ref 集合
const { name, version } = toRefs(state)
</script>
2.2 ref 详解
javascript
// ref 创建响应式引用
const count = ref(0)
// ref 也可以用于对象
const objRef = ref({
name: 'test',
value: 123
})
// 模板中会自动解包 .value
2.3 reactive 详解
javascript
// reactive 创建响应式对象
const state = reactive({
name: 'John',
age: 30,
address: {
city: 'Beijing',
street: 'Main St'
}
})
// 嵌套对象也是响应式的
state.address.city = 'Shanghai' // 触发响应
// 注意事项:
// 1. 只能用于对象类型
// 2. 替换整个对象会失去响应性
// 3. 解构会失去响应性
2.4 响应式工具函数
javascript
import {
isRef,
unref,
toRef,
toValue,
shallowRef,
triggerRef,
markRaw,
shallowReactive,
readonly
} from 'vue'
// isRef: 检查是否为 ref
console.log(isRef(count)) // true
// unref: 如果是 ref 返回 value,否则返回本身
const value = unref(maybeRef)
// toRef: 为响应式对象的属性创建 ref
const nameRef = toRef(state, 'name')
// shallowRef: 浅层 ref(只跟踪 .value 变化)
const shallowObj = shallowRef({ a: 1 })
shallowObj.value.a = 2 // 不会触发响应!
// readonly: 创建只读代理
const readOnlyState = readonly(state)
readOnlyState.name = 'new' // 会报错
// markRaw: 标记对象为"原始",不会被转换为响应式
const nonReactive = markRaw({ shouldNotBeReactive: true })
3. 计算属性和侦听器
3.1 计算属性
vue
<script setup>
import { ref, computed } from 'vue'
const price = ref(100)
const quantity = ref(2)
// 计算属性(只读)
const total = computed(() => {
return price.value * quantity.value
})
// 计算属性(可写)
const fullName = computed({
get() {
return `${firstName.value} ${lastName.value}`
},
set(newValue) {
const [first, last] = newValue.split(' ')
firstName.value = first
lastName.value = last || ''
}
})
</script>
3.2 侦听器
vue
<script setup>
import { ref, watch, watchEffect } from 'vue'
const count = ref(0)
const state = reactive({ a: 1, b: 2 })
// watch: 监听单个或多个源
watch(count, (newVal, oldVal) => {
console.log(`count变化: ${oldVal} -> ${newVal}`)
})
// 监听多个源
watch([count, () => state.a], ([newCount, newA], [oldCount, oldA]) => {
console.log('多个源变化')
})
// 深度监听
watch(
state,
(newVal, oldVal) => {
// 注意:newVal 和 oldVal 一样
console.log('state 深度变化')
},
{ deep: true }
)
// 立即执行
watch(count, callback, { immediate: true })
// watchEffect: 立即执行,自动追踪依赖
watchEffect(() => {
console.log(`count: ${count.value}, a: ${state.a}`)
// 自动追踪 count.value 和 state.a
})
// 停止侦听器
const stop = watchEffect(() => {})
stop() // 停止侦听
</script>
3.3 watch vs watchEffect
|
特性 |
watch |
watchEffect |
|
懒执行 |
✅ 默认懒执行 |
❌ 立即执行 |
|
依赖追踪 |
❌ 需要明确指定 |
✅ 自动追踪 |
|
新旧值 |
✅ 提供新旧值 |
❌ 不提供 |
|
适合场景 |
需要新旧值对比 |
不需要新旧值 |
4. 生命周期钩子
4.1 生命周期图示
text
setup() → beforeCreate → created → onBeforeMount → onMounted
→ onBeforeUpdate → onUpdated → onBeforeUnmount → onUnmounted
4.2 组合式 API 钩子
vue
<script setup>
import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
onErrorCaptured,
onActivated,
onDeactivated,
onRenderTracked,
onRenderTriggered
} from 'vue'
// 组件挂载后
onMounted(() => {
console.log('组件已挂载')
// DOM 操作可以在这里进行
})
// 组件更新前
onBeforeUpdate(() => {
console.log('组件即将更新')
})
// 组件销毁前
onBeforeUnmount(() => {
console.log('组件即将销毁')
// 清理工作
})
// 错误捕获
onErrorCaptured((err, instance, info) => {
console.error('捕获到错误:', err)
return false // 阻止错误继续向上传播
})
// KeepAlive 组件特有
onActivated(() => {
console.log('组件被激活')
})
onDeactivated(() => {
console.log('组件被停用')
})
</script>
4.3 选项式 API 钩子
javascript
export default {
data() {
return { count: 0 }
},
// 初始化前
beforeCreate() {
console.log('beforeCreate')
},
// 初始化后
created() {
console.log('created')
},
// 挂载前
beforeMount() {
console.log('beforeMount')
},
// 挂载后
mounted() {
console.log('mounted')
},
// 更新前
beforeUpdate() {
console.log('beforeUpdate')
},
// 更新后
updated() {
console.log('updated')
},
// 卸载前
beforeUnmount() {
console.log('beforeUnmount')
},
// 卸载后
unmounted() {
console.log('unmounted')
},
// 错误捕获
errorCaptured(err, instance, info) {
console.error('错误:', err)
return false
}
}
5. 模板语法
5.1 文本插值
vue
<template>
<!-- 文本插值 -->
<p>{{ message }}</p>
<!-- 原始 HTML -->
<p v-html="rawHtml"></p>
<!-- 属性绑定 -->
<div :id="dynamicId"></div>
<button :disabled="isDisabled">按钮</button>
<!-- 布尔属性 -->
<button :disabled="isButtonDisabled">按钮</button>
<!-- 动态绑定多个属性 -->
<div v-bind="objectOfAttrs"></div>
</template>
5.2 指令
vue
<template>
<!-- v-if / v-else-if / v-else -->
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else>C</div>
<!-- v-show -->
<div v-show="isVisible">显示/隐藏</div>
<!-- v-for -->
<li v-for="(item, index) in items" :key="item.id">
{{ index }}: {{ item.text }}
</li>
<!-- v-for 遍历对象 -->
<li v-for="(value, key, index) in myObject">
{{ index }}. {{ key }}: {{ value }}
</li>
<!-- v-on 事件处理 -->
<button @click="handleClick">点击</button>
<!-- 事件修饰符 -->
<form @submit.prevent="onSubmit">
<input @keyup.enter="submit" />
</form>
<!-- v-model 双向绑定 -->
<input v-model="message" />
<textarea v-model="text"></textarea>
<input type="checkbox" v-model="checked" />
<select v-model="selected">
<option value="A">A</option>
</select>
<!-- v-model 修饰符 -->
<input v-model.lazy="msg" /> <!-- change 事件后同步 -->
<input v-model.number="age" /> <!-- 转为数字 -->
<input v-model.trim="name" /> <!-- 去除首尾空格 -->
</template>
5.3 动态参数
vue
<template>
<!-- 动态属性名 -->
<div :[attributeName]="attributeValue"></div>
<!-- 动态事件名 -->
<button @[eventName]="handler"></button>
<!-- 动态插槽名 -->
<template #[dynamicSlotName]></template>
</template>
<script setup>
const attributeName = ref('id')
const eventName = ref('click')
const dynamicSlotName = ref('header')
</script>
6. 组件基础
6.1 组件定义
vue
<!-- 选项式 API -->
<script>
export default {
// 组件名称
name: 'MyComponent',
// 接收的 props
props: {
title: String,
count: {
type: Number,
default: 0,
required: true,
validator: value => value >= 0
}
},
// 本地状态
data() {
return {
localCount: 0
}
},
// 计算属性
computed: {
total() {
return this.count + this.localCount
}
},
// 方法
methods: {
increment() {
this.localCount++
}
},
// 生命周期
mounted() {
console.log('组件已挂载')
}
}
</script>
6.2 组合式 API 组件
vue
<!-- MyComponent.vue -->
<template>
<div>
<h2>{{ title }}</h2>
<p>{{ count }}</p>
<button @click="increment">增加</button>
</div>
</template>
<script setup>
import { ref, defineProps, defineEmits, defineExpose } from 'vue'
// 定义 props
const props = defineProps({
title: {
type: String,
required: true
},
count: {
type: Number,
default: 0
}
})
// 定义 emits
const emit = defineEmits(['update:count', 'custom-event'])
// 本地状态
const localCount = ref(0)
// 方法
const increment = () => {
localCount.value++
emit('update:count', props.count + 1)
emit('custom-event', '事件触发')
}
// 暴露给父组件的方法
const publicMethod = () => {
console.log('公共方法被调用')
}
defineExpose({
publicMethod,
localCount
})
</script>
6.3 组件注册
javascript
// 全局注册
import { createApp } from 'vue'
import MyComponent from './MyComponent.vue'
const app = createApp(App)
app.component('MyComponent', MyComponent)
// 局部注册
import MyComponent from './MyComponent.vue'
export default {
components: {
MyComponent
}
}
6.4 使用组件
vue
<template>
<!-- 使用组件 -->
<MyComponent
:title="componentTitle"
:count="countValue"
@update:count="handleUpdate"
@custom-event="handleCustom"
ref="myComponentRef"
/>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import MyComponent from './MyComponent.vue'
const componentTitle = ref('组件标题')
const countValue = ref(0)
const myComponentRef = ref()
const handleUpdate = (newCount) => {
countValue.value = newCount
}
const handleCustom = (message) => {
console.log(message)
}
onMounted(() => {
// 调用子组件暴露的方法
myComponentRef.value?.publicMethod()
})
</script>
这是 Vue 3 核心知识的第一部分,涵盖了响应式系统、计算属性和侦听器、生命周期、模板语法和组件基础。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...

