本篇内容我们将探讨以下内容。
- 什么是状态
- 为什么需要状态管理
- Angular中如何实现状态管理
- React中如何实现状态管理
- Vue中如何实现状态管理
什么是状态
三大框架都遵循组件化的开发思想。状态在这里表示组件在应用中某一时刻的外观或内容变化,它更倾向于描述一种延续的变化。

为什么需要状态管理
随着你的应用不断变大,更有意识的去关注应用状态如何组织,以及数据如何在组件之间流动会对你很有帮助。冗余或重复的状态往往是缺陷的根源。
状态管理指的是如何组织好状态,如何保持状态更新逻辑的可维护性,以及如何跨组件共享状态。
什么情况下需要状态管理呢?
- 多个视图可能都依赖于同一份状态。
- 来自不同视图的交互也可能需要更改同一份状态。
对于情景 1,一个可行的办法是将共享状态“提升”到共同的祖先组件上去,再通过 props 传递下来。然而在深层次的组件树结构中这么做的话,很快就会使得代码变得繁琐冗长。这会导致另一个问题:Prop 逐级透传问题。
对于情景 2,我们经常发现自己会直接通过模板引用获取父/子实例,或者通过触发的事件尝试改变和同步多个状态的副本。但这些模式的健壮性都不甚理想,很容易就会导致代码难以维护。
一个更简单直接的解决方案是抽取出组件间的共享状态,放在一个全局单例中来管理。
Angular中如何实现状态管理
在 Angular 中并没有状态管理这一概念,不过框架本身是一个很成熟的框架,使用 Service + RxJS 就能实现状态管理。
状态管理的示例:
user.service.ts文件
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
// 定义一个用户接口
export interface User {
id: number;
name: string;
email: string;
}
// 定义一个初始的用户状态
const initialUser: User = {
id: 0,
name: 'Guest',
email: 'guest@example.com'
};
@Injectable({
providedIn: 'root'
})
export class UserService {
// 创建一个 BehaviorSubject 来存储用户状态
private userSubject = new BehaviorSubject<User>(initialUser);
// 创建一个公开的 user$ 属性,用来订阅用户状态
user$ = this.userSubject.asObservable();
constructor() { }
// 创建一个方法,用来更新用户状态
updateUser(user: User) {
this.userSubject.next(user);
}
}
user.component.ts文件
import { Component, OnInit } from '@angular/core';
import { UserService, User } from '../user.service';
@Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
// 定义一个 user 属性,用来存储用户状态
user: User;
constructor(private userService: UserService) { }
ngOnInit(): void {
// 订阅 user$ 属性,获取用户状态
this.userService.user$.subscribe(user => {
this.user = user;
});
}
// 定义一个方法,用来模拟修改用户状态
changeUser() {
// 随机生成一个新的用户对象
const newUser: User = {
id: Math.floor(Math.random() * 100),
name: 'User' + Math.floor(Math.random() * 100),
email: 'user' + Math.floor(Math.random() * 100) + '@example.com'
};
// 调用 updateUser 方法,更新用户状态
this.userService.updateUser(newUser);
}
}
user.component.html文件
<h1>User Component</h1>
<p>User ID: {{ user.id }}</p>
<p>User Name: {{ user.name }}</p>
<p>User Email: {{ user.email }}</p>
<button (click)="changeUser()">Change User</button>
React中如何实现状态管理
对于拥有许多状态更新逻辑的组件来说,过于分散的事件处理程序可能会令人不知所措。对于这种情况,你可以将组件的所有状态更新逻辑整合到一个外部函数中,这个函数叫作 reducer。
状态管理的示例:
user.reducer.js 文件
// 定义一个初始的用户状态
const initialUser = {
id: 0,
name: 'Guest',
email: 'guest@example.com'
};
// 定义一个 reducer 函数,接收一个 state 和一个 action
export default function userReducer(state = initialUser, action) {
// 根据 action 的类型返回一个新的状态对象
switch (action.type) {
case 'UPDATE_USER':
return action.payload;
default:
return state;
}
}
user.component.jsx 文件
import React, { useReducer } from 'react';
import userReducer from './user.reducer';
function UserComponent() {
// 使用 useReducer hook 创建一个 state 和一个 dispatch 函数
const [user, dispatch] = useReducer(userReducer, initialUser);
// 定义一个方法,用来模拟修改用户状态
function changeUser() {
// 随机生成一个新的用户对象
const newUser = {
id: Math.floor(Math.random() * 100),
name: 'User' + Math.floor(Math.random() * 100),
email: 'user' + Math.floor(Math.random() * 100) + '@example.com'
};
// 调用 dispatch 函数,发送一个类型为 UPDATE_USER 的 action,并将新的用户对象作为 payload
dispatch({ type: 'UPDATE_USER', payload: newUser });
}
return (
<div>
<h1>User Component</h1>
<p>User ID: {user.id}</p>
<p>User Name: {user.name}</p>
<p>User Email: {user.email}</p>
<button onClick={changeUser}>Change User</button>
</div>
);
}
export default UserComponent;
Vue中如何实现状态管理
在 Vue 中可以抽取出组件间的共享状态,放在一个全局单例中来管理。
状态管理的示例:
store.ts 文件
import { ref } from 'vue';
// 定义一个用户接口
export interface User {
id: number;
name: string;
email: string;
}
// 定义一个初始的用户状态
const initialUser: User = {
id: 0,
name: 'Guest',
email: 'guest@example.com'
};
// 使用 ref 函数创建一个响应式的状态对象
export const user = ref<User>(initialUser);
// 定义一个函数,用来更新用户状态
export function updateUser(user: User) {
// 将新的用户对象赋值给 user
user.value = user;
}
user.component.vue 文件
<template>
<div>
<h1>User Component</h1>
<p>User ID: {{ user.id }}</p>
<p>User Name: {{ user.name }}</p>
<p>User Email: {{ user.email }}</p>
<button @click="changeUser">Change User</button>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import { user, updateUser, User } from './store.ts';
// 使用 computed 函数创建一个计算属性,用于返回 user 中的数据
const user = computed(() => user.value);
// 定义一个方法,用来模拟修改用户状态
function changeUser() {
// 随机生成一个新的用户对象
const newUser: User = {
id: Math.floor(Math.random() * 100),
name: 'User' + Math.floor(Math.random() * 100),
email: 'user' + Math.floor(Math.random() * 100) + '@example.com'
};
// 调用 updateUser 函数,更新用户状态
updateUser(newUser);
}
</script>
小结
在三大框架中, Angular 对状态管理并没有做过多的描述,这个可能与它是面向对象类的编程理念相关,可以通过封装类库来实现状态管理。在React与Vue中,状态是最核心的概念,所有组件中的交互与数据渲染都与状态有关。
文章参考链接:
发表回复