作为一个后端开发者,我们可能偶尔需要接触前端代码,或者至少要和前端的同事协作。Vue作为目前最流行的前端框架之一,从Vue2到Vue3的变化其实挺大的,我会总结一下常见的区别和不同。
一、响应式数据:从"死板"到"灵活"
Vue2的限制:
- 不能直接给对象添加新属性(就像数据库表不能随便加字段)
- 不能直接通过索引修改数组(
this.hobbies[0] = \'足球\'不会触发更新)
// Vue2的响应式数据
data() {
return {
user: {
name: \'张三\',
age: 25
},
hobbies: [\'篮球\', \'音乐\']
}
}
Vue3的改变:你可以更加灵活的修改响应式数据。
// Vue3的响应式数据
setup() {
const user = reactive({
name: \'张三\',
age: 25
})
const hobbies = ref([\'篮球\', \'音乐\'])
// 现在这些操作都能自动触发更新
user.gender = \'男\' //添加新属性
hobbies.value[0] = \'足球\' //直接修改数组
}
二、代码组织:从"Options API"到"Composition API"
作为后端开发者,肯定熟悉按功能组织代码的方式。Vue2和Vue3在代码组织上的区别,就像把代码从"按类型分类"改成"按功能模块"分类。
Vue2:Options API(按类型分类)
export default {
// 数据区 - 像把所有的变量声明放一起
data() {
return {
users: [],
products: [],
loading: false
}
},
// 方法区 - 像把所有的Service方法放一起
methods: {
fetchUsers() { /* 获取用户 */ },
fetchProducts() { /* 获取产品 */ }
},
// 计算属性区 - 像把所有的工具方法放一起
computed: {
activeUsers() { /* 过滤活跃用户 */ }
},
// 生命周期区 - 像初始化方法
mounted() {
this.fetchUsers();
this.fetchProducts();
}
}这就像你的Java项目结构:
src
├── controllers // 所有Controller
├── services // 所有Service
├── repositories // 所有DAO
└── models // 所有DTO找用户相关功能时,你需要在Controller、Service、DAO包之间来回跳转。
Vue3:Composition API(按功能分类)
import { ref, onMounted } from \'vue\';
export default {
setup() {
// 用户功能模块 - 像用户的Service
const users = ref([]);
const loading = ref(false);
const fetchUsers = async () => {
loading.value = true;
users.value = await userService.getUsers();
loading.value = false;
};
// 产品功能模块 - 像产品的Service
const products = ref([]);
const fetchProducts = async () => {
products.value = await productService.getProducts();
};
// 初始化 - 像@PostConstruct
onMounted(() => {
fetchUsers();
fetchProducts();
});
return {
users,
products,
loading
};
}
}
现在代码结构更像:
src
├── user // 用户相关功能
│ ├── UserController.java
│ ├── UserService.java
│ └── UserRepository.java
└── product // 产品相关功能
├── ProductController.java
├── ProductService.java
└── ProductRepository.java为什么这么改:
- 功能集中:用户相关代码在一起,产品相关代码在一起
- 复用方便:可以把用户功能提取成独立函数(就像提取Service)
- 维护简单:修改用户功能时,不用在文件里上下滚动查找
- 类型友好:像Java一样有清晰的变量和方法类型
两种API的对比
| 特点 | Options API (Vue2) | Composition API (Vue3) |
|---|---|---|
| 代码组织 | 按类型分组(data/methods等) | 按功能模块分组 |
| 功能复用 | Mixins(容易命名冲突) | 自定义函数(像工具类) |
| 类型支持 | 有限支持 | 完整的TypeScript支持 |
| 代码阅读 | 需要上下滚动 | 相关代码在一起 |
| 适合场景 | 简单页面 | 复杂组件和大型项目 |
作为后端开发者,Composition API确实更符合我的思维习惯。
三、生命周期函数:其实就是改了个更准确的名字
| Vue2 | Vue3 |
|---|---|
| beforeCreate | setup() |
| created | setup() |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeDestroy | onBeforeUnmount |
| destroyed | onUnmounted |
四、模板改进:更加灵活
1.不再强制要求单根元素:
<!-- Vue2必须包一层div -->
<template>
<div>
<header></header>
<main></main>
</div>
</template>
<!-- Vue3可以直接写多个标签 -->
<template>
<header></header>
<main></main>
</template>2.更好的v-model:
<!-- Vue2只能绑定一个v-model -->
<UserForm v-model=\"formData\" />
<!-- Vue3可以绑定多个 -->
<UserForm
v-model:name=\"formData.name\"
v-model:age=\"formData.age\"
/>五、TypeScript支持:从"能用"到"好用"
Vue2对TypeScript的支持就像早期Spring对泛型的支持 - 能用但不太顺手。Vue3则是从底层使用TypeScript进行重写:
// Vue3 + TypeScript示例
<script setup lang=\"ts\">
// 定义接口(就像Java的DTO)
interface User {
id: number
name: string
age?: number // 可选属性
}
// 响应式数据(自动类型推断)
const user = ref<User>({
id: 1,
name: \'张三\'
})
// 方法也有完整类型检查
const updateUser = (newUser: User) => {
user.value = newUser
}
</script>
为什么这么改:就像我们离不开Java的类型安全一样,前端大型项目也需要好的类型支持。
评论