Angular中@Injectable()服务为何持续执行登录检查函数?
嘿,这个问题我之前也碰到过,其实核心原因是Angular的变更检测机制在搞事情,我给你拆解清楚:
为什么loggedin()会持续执行?
Angular的变更检测会在很多场景下自动运行——比如用户点击按钮、HTTP请求完成、路由切换、甚至浏览器窗口大小改变的时候。而你在*ngIf里直接调用了service.loggedin()函数,每次变更检测触发时,这个函数都会被重新执行一次,所以控制台才会一直打印adminvalue。
简单说:模板里的绑定表达式(包括*ngIf的条件),在每一轮变更检测中都会被重新计算。如果是函数的话,就意味着函数会被反复调用。
路由到页面时的触发逻辑
当你路由到新页面时,Angular会完成以下几步,间接触发这个函数:
- 初始化目标组件,执行它的生命周期钩子(比如
ngOnInit); - 启动组件的变更检测周期,此时模板里所有的绑定表达式都会被计算,包括你写的
service.loggedin(); - 如果路由过程中还有其他异步操作(比如路由守卫、组件数据加载),操作完成后又会触发新一轮变更检测,函数也就再被调用一次。
怎么解决这个问题?
别在模板里直接调用函数!改用属性绑定的方式,把登录状态存在组件的一个属性里,只在状态变化时更新它:
- 在组件里定义一个存储登录状态的属性:
isLoggedIn = false;
- 初始化并监听状态变化:
ngOnInit() { // 页面加载时先检查一次登录状态 this.updateLoginStatus(); // 监听localStorage的变化(处理多标签页登录状态同步的情况) window.addEventListener('storage', () => this.updateLoginStatus()); } updateLoginStatus() { // 用!!把null/undefined转成布尔值 this.isLoggedIn = !!localStorage.getItem('user'); }
- 在登录/登出方法里手动更新状态:
login() { // 你的登录逻辑... localStorage.setItem('user', JSON.stringify(userData)); this.updateLoginStatus(); } logout() { // 你的登出逻辑... localStorage.removeItem('user'); this.updateLoginStatus(); }
- 最后修改模板,直接用属性判断:
<button (click)="login()" *ngIf="!isLoggedIn">Login</button> <button (click)="logout()" *ngIf="isLoggedIn">Logout</button>
这样改之后,只有当登录状态真的变化时,isLoggedIn属性才会更新,变更检测时只需要对比属性值,不会反复执行函数,控制台也不会一直打印日志了,性能也更好~
内容的提问来源于stack exchange,提问作者codedamn
相关产品推荐
相关产品推荐

