Angular 16中能否在effect()函数中获取旧值(类似Vue.js的watch)?
Angular 16 Effect 获取旧值的实现方案
Angular的effect()本身不会像Vue的watch那样自动传入新旧值,但可以通过手动在effect外部维护变量存储上一次的状态来实现类似的新旧值对比功能,结合onCleanup还能处理资源释放场景。
单个Signal的新旧值监听
直接在effect外部初始化旧值,每次effect触发时对比当前值与旧值,完成逻辑后更新旧值:
import { signal, effect } from '@angular/core'; // 定义要监听的signal const count = signal(0); // 初始化旧值为signal的初始值 let oldCount = count(); effect(() => { const currentCount = count(); // 仅当值变化时执行逻辑 if (currentCount !== oldCount) { console.log(`旧值: ${oldCount}, 新值: ${currentCount}`); // 这里可以做差异对比、资源释放等操作 oldCount = currentCount; // 更新旧值为当前值 } });
多个Signal/Computed的新旧值监听
如果需要监听多个依赖,可以用对象存储多个旧值,分别对比:
import { signal, effect } from '@angular/core'; const userName = signal('Alice'); const userAge = signal(25); // 用对象存储多个旧值 const oldValues = { name: userName(), age: userAge() }; effect(() => { const currentName = userName(); const currentAge = userAge(); if (currentName !== oldValues.name) { console.log(`姓名旧值: ${oldValues.name}, 新值: ${currentName}`); oldValues.name = currentName; } if (currentAge !== oldValues.age) { console.log(`年龄旧值: ${oldValues.age}, 新值: ${currentAge}`); oldValues.age = currentAge; } });
结合onCleanup处理资源释放
当需要在值变化时释放旧资源(比如取消订阅、清理定时器),可以结合onCleanup和旧值变量实现:
import { signal, effect } from '@angular/core'; interface User { id: string; // 假设存在需要订阅的资源 // loadData: () => Observable<any>; } const currentUser = signal<User | null>(null); let oldUser: User | null = currentUser(); effect((onCleanup) => { const user = currentUser(); if (user !== oldUser) { // 释放旧用户相关资源 if (oldUser) { console.log(`清理旧用户 ${oldUser.id} 的资源`); // 示例:取消旧订阅 // oldUser.subscription?.unsubscribe(); } // 处理新用户逻辑 if (user) { console.log(`加载新用户 ${user.id} 的数据`); // const subscription = user.loadData().subscribe(...); // 用onCleanup确保组件销毁时清理新资源 // onCleanup(() => subscription.unsubscribe()); } oldUser = user; } });
这种手动维护旧值的方式是目前最直接的解决方案,因为effect的设计定位是响应依赖变化执行副作用,而非专门的新旧值对比监听,因此需要自行维护状态来模拟Vue watch的新旧值功能。
内容的提问来源于stack exchange,提问作者Peter T.
相关产品推荐
相关产品推荐

