Vue 3核心特性与开发实践指南
一、Vue 3主要特性
Vue 3在前代基础上进行了全面重构,引入了多项重要改进:
- 组合式API:通过函数方式组织代码逻辑,提升代码复用性和可维护性
- 性能优化:渲染效率和数据初始化速度显著提升
- TypeScript原生支持:提供完整的类型定义,代码更加可靠
- 更小体积:Tree-shaking支持使最终打包体积更紧凑
- 响应式系统升级:采用Proxy替代Object.defineProperty,监听效率更高
二、项目目录结构
标准Vue 3项目的文件组织方式:
my-app/
├── node_modules/ # 项目依赖包目录
├── public/ # 公共静态资源
│ └── index.html # HTML入口文件
├── src/ # 源代码主目录
│ ├── assets/ # 图片、字体、样式等资源
│ ├── components/ # 业务组件存放目录
│ ├── views/ # 页面级组件
│ ├── App.vue # 根组件
│ └── main.ts # 应用入口文件
└── package.json # 项目配置与依赖声明
三、核心概念解析
1.Vue应用实例
Vue应用本质上是创建一个根实例并将其挂载到DOM元素的过程。
// main.ts
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
app.mount('#app');
createApp():创建Vue应用实例,接收根组件作为参数mount():将应用挂载到指定DOM元素
2.Options API与Composition API对比
Options API(配置式)
将数据、方法、计算属性分散在不同选项中管理:
<template>
<div class="user-card">
<h3>用户信息</h3>
<p>用户名:{{ username }}</p>
<p>等级:{{ level }}</p>
<p>邮箱:{{ email }}</p>
<button @click="updateLevel">升级</button>
<button @click="showEmail">查看邮箱</button>
</div>
</template>
<script lang="ts">
export default {
name: 'UserCard',
data() {
return {
username: '王小明',
level: 1,
email: 'wang@example.com'
}
},
methods: {
updateLevel() {
this.level++;
},
showEmail() {
console.log(`邮箱:${this.email}`);
}
}
}
</script>
<style scoped>
.user-card {
background-color: #eef2f5;
padding: 20px;
border-radius: 8px;
}
button {
margin-right: 8px;
}
</style>
Composition API(组合式)
以函数形式组织相关逻辑代码,便于功能复用和维护。
3.组件化开发
组件是Vue应用的基本构建单元,每个组件包含模板、逻辑和样式。
<!-- App.vue -->
<template>
<div id="app">
<h1>Vue 3学习笔记</h1>
<ArticleList />
</div>
</template>
<script setup>
import ArticleList from './components/ArticleList.vue';
</script>
<style scoped>
h1 {
color: #2c3e50;
font-size: 24px;
}
</style>
<template>:组件的HTML模板结构<script>:组件的业务逻辑<style scoped>:组件私有样式,防止污染其他组件
4.数据绑定机制
Vue实现数据与视图的双向同步。
文本插值
<template>
<div class="greeting">
<h1>{{ title }}</h1>
</div>
</template>
<script setup>
import { ref } from 'vue';
const title = ref('欢迎学习Vue 3');
</script>
属性绑定
![头像]()
<!-- 等价于 -->
![头像]()
表单双向绑定
<template>
<div class="form">
<input v-model="username" placeholder="请输入用户名" />
<p>当前输入:{{ username }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
const username = ref('');
</script>
5.事件处理
使用@简写形式绑定事件处理器:
<template>
<div class="actions">
<button @click="handleSubmit">提交</button>
</div>
</template>
<script setup>
function handleSubmit() {
console.log('表单已提交');
}
</script>
6.计算属性
基于响应式数据派生新值,具备缓存机制:
<template>
<div>
<p>原字符串:{{ originalText }}</p>
<p>反转后:{{ reversedText }}</p>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const originalText = ref('Vue3学习');
const reversedText = computed(() => {
return originalText.value.split('').reverse().join('');
});
</script>
计算属性会缓存结果,仅当依赖的响应式数据变化时才重新计算。
7.生命周期钩子
Vue组件在不同的生命周期阶段提供钩子函数:
| 钩子函数 | 执行时机 |
|---|---|
| onMounted | 组件挂载到DOM后 |
| onUpdated | 数据更新后 |
| onUnmounted | 组件卸载前 |
import { ref, onMounted, onUpdated } from 'vue';
export default {
setup() {
const message = ref('初始化');
onMounted(() => {
console.log('组件已挂载');
});
onUpdated(() => {
console.log('数据已更新');
});
return { message };
}
}
四、Composition API详解
组合式API是Vue 3的核心特性,通过函数方式组织组件逻辑。
1.ref与reactive
ref函数
定义基本类型或对象类型的响应式数据:
import { ref } from 'vue';
const count = ref(0);
const userInfo = ref({
name: '张三',
age: 25
});
// 在脚本中修改需使用.value
function increment() {
count.value++;
}
reactive函数
定义对象类型的响应式数据:
import { reactive } from 'vue';
const state = reactive({
isLoading: false,
dataList: [] as string[]
});
function loadData() {
state.isLoading = true;
}
使用建议
- 基本类型数据必须使用ref
- 简单对象(层级不深)可用ref或reactive
- 复杂深层对象推荐使用reactive
注意
// 错误做法 - 失去响应式
state = { new: 'data' }
// 正确做法 - 使用Object.assign
Object.assign(state, { new: 'data' });
2.toRef与toRefs
将响应式对象的属性转换为独立的ref,保持与源对象的响应式连接:
<template>
<div class="profile">
<h3>姓名:{{ name }}</h3>
<h3>年龄:{{ age }}</h3>
<h3>地址:{{ address }}</h3>
<button @click="modifyName">修改姓名</button>
<button @click="modifyAge">修改年龄</button>
</div>
</template>
<script lang="ts" setup>
import { reactive, toRefs } from 'vue';
const person = reactive({
name: '李华',
age: 28,
address: '北京'
});
// 使用toRefs批量转换
const { name, age, address } = toRefs(person);
function modifyName() {
name.value += '~';
}
function modifyAge() {
age.value++;
}
</script>
<style scoped>
</style>
3.computed计算属性
<template>
<div class="input-area">
<label>姓氏:<input v-model="surname" /></label>
<label>名字:<input v-model="givenName" /></label>
<button @click="updateFullName">重置为赵六</button>
<p>完整姓名:{{ fullName }}</p>
</div>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue';
const surname = ref('赵');
const givenName = ref('六');
// 可读可写的计算属性
const fullName = computed({
get: () => `${surname.value}-${givenName.value}`,
set: (val: string) => {
const [first, last] = val.split('-');
surname.value = first;
givenName.value = last;
}
});
function updateFullName() {
fullName.value = '钱-八';
}
</script>
<style scoped>
label {
display: block;
margin: 10px 0;
}
</style>
4.watch监听器
监听响应式数据变化并执行相应逻辑。
监听基本类型数据
<template>
<div>
<h2>当前计数:{{ counter }}</h2>
<button @click="add">加一</button>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
const counter = ref(0);
function add() {
counter.value++;
}
const stopWatch = watch(counter, (newVal, oldVal) => {
console.log(`计数从${oldVal}变为${newVal}`);
if (newVal >= 10) {
stopWatch();
}
});
</script>
监听对象类型数据
<template>
<div>
<h3>产品信息</h3>
<p>名称:{{ product.name }}</p>
<p>价格:{{ product.price }}</p>
<button @click="changeName">改名称</button>
<button @click="changePrice">改价格</button>
<button @click="replaceProduct">替换整个对象</button>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
const product = ref({
name: 'iPhone',
price: 5999
});
function changeName() {
product.value.name += '~';
}
function changePrice() {
product.value.price += 100;
}
function replaceProduct() {
product.value = {
name: 'iPad',
price: 4999
};
}
// 监听对象需要开启深度监听
watch(product, (newVal, oldVal) => {
console.log('对象变化:', newVal, oldVal);
}, { deep: true, immediate: true });
</script>
监听reactive定义的数据
<template>
<div>
<h3>用户资料</h3>
<p>姓名:{{ user.nickname }}</p>
<p>积分:{{ user.points }}</p>
<button @click="updateNickname">修改昵称</button>
<button @click="updatePoints">增加积分</button>
<button @click="replaceUser">替换整个对象</button>
</div>
</template>
<script setup lang="ts">
import { reactive, watch } from 'vue';
const user = reactive({
nickname: '游客',
points: 100
});
function updateNickname() {
user.nickname += '~';
}
function updatePoints() {
user.points += 50;
}
function replaceUser() {
Object.assign(user, {
nickname: '新用户',
points: 500
});
}
// reactive定义的对象默认开启深度监听,无法关闭
watch(user, (newVal, oldVal) => {
console.log('用户数据变化:', newVal);
});
</script>
监听对象内部属性
<template>
<div>
<p>车辆信息:{{ car.brand }} - {{ car.model }}</p>
<button @click="updateBrand">修改品牌</button>
<button @click="updateModel">修改型号</button>
</div>
</template>
<script setup lang="ts">
import { reactive, watch } from 'vue';
const car = reactive({
brand: '比亚迪',
model: '汉'
});
function updateBrand() {
car.brand = '红旗';
}
function updateModel() {
car.model = 'H9';
}
// 监听基本类型属性使用函数形式
watch(() => car.brand, (newVal, oldVal) => {
console.log(`品牌从${oldVal}变为${newVal}`);
});
// 监听对象类型属性可使用函数形式,开启深度监听
watch(() => car, (newVal, oldVal) => {
console.log('车辆信息变化', newVal);
}, { deep: true });
</script>
同时监听多个数据源
<template>
<div>
<p>姓名:{{ person.name }}</p>
<p>年龄:{{ person.age }}</p>
<p>车辆:{{ person.car.brand }}</p>
</div>
</template>
<script setup lang="ts">
import { reactive, watch } from 'vue';
const person = reactive({
name: '陈总',
age: 35,
car: {
brand: '特斯拉',
model: 'Model 3'
}
});
// 同时监听多个数据源
watch(
[() => person.name, () => person.car],
([newName, newCar], [oldName, oldCar]) => {
console.log('数据变化:', newName, newCar);
},
{ deep: true }
);
</script>
5.watchEffect
自动追踪依赖并响应式执行:
<template>
<div>
<h2>监控系统</h2>
<p>温度:{{ temperature }}°C</p>
<p>压力:{{ pressure }}MPa</p>
<button @click="increaseTemp">升温</button>
<button @click="increasePressure">升压</button>
</div>
</template>
<script setup lang="ts">
import { ref, watchEffect } from 'vue';
const temperature = ref(20);
const pressure = ref(0.5);
function increaseTemp() {
temperature.value += 10;
}
function increasePressure() {
pressure.value += 0.2;
}
// 自动追踪函数内使用的所有响应式数据
watchEffect(() => {
if (temperature.value >= 80 || pressure.value >= 0.8) {
console.log('触发警报:参数超标!');
}
});
</script>
<style scoped>
p {
font-size: 18px;
}
</style>
watch与watchEffect区别
- watch:需要明确指定监听的数据源
- watchEffect:自动收集函数内使用的所有响应式依赖
五、setup组件配置
setup是Composition API的入口函数,在组件实例创建前执行:
<template>
<div>
<h2>{{ message }}</h2>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const message = ref('Hello Vue 3');
onMounted(() => {
console.log('setup中的钩子执行了');
});
</script>
setup函数返回的所有属性和方法都可在模板中直接使用,访问this会得到undefined。