Vue.js 架构设计深度解析
原创2024/1/25大约 3 分钟
Vue.js 架构设计深度解析
Vue.js 采用 MVVM (Model-View-ViewModel) 架构模式,通过数据驱动和组件化的思想构建用户界面。
Vue 架构概览
上图展示了 Vue.js 的三层架构:
1. 视图层 (View)
视图层是用户看到和交互的界面,由 Template 或 JSX 编写。
<template>
<div class="user-profile">
<h1>{{ user.name }}</h1>
<p>{{ user.email }}</p>
<button @click="updateProfile">更新资料</button>
</div>
</template>特点:
- 🎨 声明式渲染
- 📝 模板语法简洁
- 🔄 自动更新 DOM
2. ViewModel 层
ViewModel 是 Vue 实例,负责连接 View 和 Model,处理数据绑定和事件监听。
export default {
data() {
return {
user: {
name: 'Alice',
email: 'alice@example.com'
}
}
},
methods: {
updateProfile() {
// 更新逻辑
this.user.name = 'Bob'
}
},
computed: {
displayName() {
return `用户: ${this.user.name}`
}
}
}核心功能:
- ✨ 数据响应式
- 🔗 双向数据绑定
- 📊 计算属性
- 👀 侦听器
- 🎯 事件处理
3. 数据层 (Model)
Model 是纯 JavaScript 对象,存储应用的数据和业务逻辑。
// userService.js
class UserService {
async fetchUser(id) {
const response = await fetch(`/api/users/${id}`)
return response.json()
}
async updateUser(id, data) {
const response = await fetch(`/api/users/${id}`, {
method: 'PUT',
body: JSON.stringify(data)
})
return response.json()
}
}
export default new UserService()响应式原理
Vue 3 使用 Proxy 实现响应式系统:
// 简化的响应式实现
function reactive(target) {
return new Proxy(target, {
get(target, key, receiver) {
// 依赖收集
track(target, key)
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver)
// 触发更新
trigger(target, key)
return result
}
})
}响应式流程
1. 组件渲染时,访问响应式数据
↓
2. Getter 被触发,收集依赖 (track)
↓
3. 数据变化时,Setter 被触发
↓
4. 通知所有依赖进行更新 (trigger)
↓
5. 组件重新渲染组件通信
Props Down, Events Up
<!-- 父组件 -->
<template>
<ChildComponent
:user="currentUser"
@update="handleUpdate"
/>
</template>
<!-- 子组件 -->
<template>
<div>
<p>{{ user.name }}</p>
<button @click="$emit('update', newData)">
更新
</button>
</div>
</template>
<script>
export default {
props: {
user: {
type: Object,
required: true
}
},
emits: ['update']
}
</script>Provide / Inject
// 祖先组件
export default {
provide() {
return {
theme: this.theme,
updateTheme: this.updateTheme
}
}
}
// 后代组件
export default {
inject: ['theme', 'updateTheme']
}虚拟 DOM
Vue 使用虚拟 DOM 提高性能:
// 虚拟 DOM 节点
const vnode = {
type: 'div',
props: {
class: 'container'
},
children: [
{
type: 'h1',
children: 'Hello Vue'
}
]
}
// Diff 算法比较新旧虚拟 DOM
// 只更新变化的部分Diff 算法优化
- 🎯 同层比较
- 🔑 Key 值优化
- 📦 静态提升
- 🚀 Patch Flag
生命周期
<script setup>
import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted
} from 'vue'
onBeforeMount(() => {
console.log('组件挂载前')
})
onMounted(() => {
console.log('组件已挂载')
// DOM 已就绪,可以访问 refs
})
onBeforeUpdate(() => {
console.log('组件更新前')
})
onUpdated(() => {
console.log('组件已更新')
})
onBeforeUnmount(() => {
console.log('组件卸载前')
// 清理定时器、取消订阅等
})
onUnmounted(() => {
console.log('组件已卸载')
})
</script>状态管理 (Pinia)
// stores/user.js
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
user: null,
isLoggedIn: false
}),
getters: {
displayName: (state) => {
return state.user?.name || 'Guest'
}
},
actions: {
async login(credentials) {
const user = await api.login(credentials)
this.user = user
this.isLoggedIn = true
},
logout() {
this.user = null
this.isLoggedIn = false
}
}
})
// 在组件中使用
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()性能优化
1. 懒加载
// 路由懒加载
const routes = [
{
path: '/user',
component: () => import('./views/User.vue')
}
]2. KeepAlive
<template>
<KeepAlive>
<component :is="currentView" />
</KeepAlive>
</template>3. v-memo
<template>
<div v-memo="[user.id, user.name]">
<!-- 只在 id 或 name 变化时更新 -->
{{ user.name }}
</div>
</template>架构最佳实践
- 单一职责: 每个组件只做一件事
- 组件拆分: 合理拆分大组件
- 状态提升: 共享状态放在父组件或状态管理中
- Props 验证: 使用 TypeScript 或 PropTypes
- 避免过度优化: 先保证功能正确,再优化性能
总结
Vue.js 的架构设计简洁而强大,通过 MVVM 模式实现了数据驱动的视图更新。理解 Vue 的架构原理,能够帮助我们写出更高质量的代码。