Angular使用Ngrx时selectedPost已存入store和localStorage但模板不显示
问题核心原因
localStorage仅支持存储字符串类型数据,你在存取selectedPost时没有做JSON序列化/反序列化处理,导致存入store的selectedPost是字符串而非Post对象,模板访问属性时返回undefined,因此没有内容渲染。
修复步骤
- 修正列表页跳转时的存储逻辑
你在posts-list.component的标题点击跳转事件中,存储到localStorage前需要序列化对象:
// 你的点击跳转逻辑示例 onPostClick(post: Post) { // 新增JSON序列化 localStorage.setItem('theSelectedPost', JSON.stringify(post)); this.router.navigate(['/posts', post.id]); }
- 修正
post.component.ts中读取localStorage的逻辑
读取时要对字符串做反序列化转成Post对象:
ngOnInit(): void { const savedPost = localStorage.getItem('theSelectedPost'); if(savedPost) { // 新增JSON反序列化 this.store.dispatch(setSelectedPost({post: JSON.parse(savedPost)})); } this.post$ = this.store.pipe(select(getSelectedPost)); this.postUrl = this.route.snapshot.paramMap.get("id"); }
- 可选优化:模板统一订阅
你当前模板多次使用async管道会产生多个重复订阅,可合并为单个订阅简化代码:
<ng-container *ngIf="post$ | async as post"> <div class="title"> {{post.title}} </div> <div class="content"> {{post.content}} </div> <img [src]="post.imageSrc"> <div class="categories"> <div class="category" *ngFor="let category of post.categories"> {{category}} </div> </div> </ng-container> <form [formGroup]="formGroup"> Update Post: <br> <input type="text" placeholder="Title..." formControlName="title"> <br> <textarea placeholder="Content..." formControlName="content"></textarea> <br> <button (click)="updatePost(formGroup.value)">Update</button> </form>
- 额外兼容场景(可选)
如果用户直接通过地址栏访问/posts/:id路由,localStorage中没有对应缓存时,可从store已加载的文章列表中匹配对应id的文章设置为选中状态,补充逻辑如下:
import { take } from 'rxjs'; // ...其他导入 ngOnInit(): void { const postId = this.route.snapshot.paramMap.get("id"); const savedPost = localStorage.getItem('theSelectedPost'); if(savedPost) { const parsedPost = JSON.parse(savedPost); // 校验缓存的文章id和当前路由id是否一致,避免打开错误文章 if(parsedPost.id.toString() === postId) { this.store.dispatch(setSelectedPost({post: parsedPost})); } else { this.loadTargetPost(postId); } } else { this.loadTargetPost(postId); } this.post$ = this.store.pipe(select(getSelectedPost)); this.postUrl = postId; } private loadTargetPost(postId: string) { this.store.pipe( select(getPosts), take(1) ).subscribe(posts => { const targetPost = posts.find(p => p.id.toString() === postId); if(targetPost) { this.store.dispatch(setSelectedPost({post: targetPost})); localStorage.setItem('theSelectedPost', JSON.stringify(targetPost)); } }) }
内容的提问来源于stack exchange,提问作者muaaz
相关产品推荐
相关产品推荐

