Angular 6 BehaviorSubject 使用 LocalStorage

Posted

技术标签:

【中文标题】Angular 6 BehaviorSubject 使用 LocalStorage【英文标题】:Angular 6 BehaviorSubject using LocalStorage 【发布时间】:2019-01-12 13:21:34 【问题描述】:

我在刷新页面后保存数据时遇到问题。我正在使用共享服务在不相关的组件之间传递数据。我在 Google 上搜索了有关 LocalStorage 以及如何使用它的所有信息,但没有得到答案。 LocalStorage 有很多不同的实现,我不知道什么适合我的项目。 我有将课程 ID 传递给服务的课程详细信息组件,以及获取该 ID 并使用此 ID 请求 http 获取的课程播放组件。每次我刷新课程播放页面时,数据都会消失。我需要有关在刷新后使用 LocalStorage 保存此数据时要写入的内容和位置的帮助(并在我在不同的课程中更新 id 时)。 我附上相关代码:

course.service

import  Injectable  from '@angular/core';
import  HttpClient, HttpErrorResponse  from '@angular/common/http';
import  BehaviorSubject  from 'rxjs';

import  Observable, throwError  from 'rxjs';
import  catchError, groupBy  from 'rxjs/operators';

import  ICourse  from './course';

// Inject Data from Rails app to Angular app
@Injectable()
export class CourseService

  // JSON url to get data from
  private url = 'http://localhost:3000/courses';
  private courseUrl = 'http://localhost:3000/courses.json';

  // Subscribe data
  private courseId = new BehaviorSubject(1);
  public courseId$ = this.courseId.asObservable();

  // here we set/change value of the observable
  setId(courseId) 
    this.courseId.next(courseId)
  

  constructor(private http: HttpClient)  

  // Handle Any Kind of Errors
  private handleError(error: HttpErrorResponse) 

    // A client-side or network error occured. Handle it accordingly.
    if (error.error instanceof ErrorEvent) 
      console.error('An error occured:', error.error.message);
    

    // The backend returned an unsuccessful response code.
    // The response body may contain clues as to what went wrong.
    else 
      console.error(
        'Backend returned code $error.status, ' +
        'body was $error.error');
    

    // return an Observable with a user-facing error error message
    return throwError(
      'Something bad happend; please try again later.');
  

  // Get All Courses from Rails API App
  getCourses(): Observable<ICourse[]> 
  const coursesUrl = `$this.url` + '.json';

  return this.http.get<ICourse[]>(coursesUrl)
      .pipe(catchError(this.handleError));
  

  // Get Single Course by id. will 404 if id not found
  getCourse(id: number): Observable<ICourse> 
    const detailUrl = `$this.url/$id` + '.json';
    return this.http.get<ICourse>(detailUrl)
        .pipe(catchError(this.handleError));
  



course-detail.component

import  Component, OnInit, Pipe, PipeTransform  from '@angular/core';
import  ActivatedRoute, Router, Routes  from '@angular/router';

import  ICourse  from '../course';
import  CourseService  from '../course.service';


// Course-detail decorator
@Component(
  selector: 'lg-course-detail',
  templateUrl: './course-detail.component.html',
  styleUrls: ['./course-detail.component.sass']
)

export class CourseDetailComponent implements OnInit 
  course: ICourse;
  errorMessage: string;

  constructor(private courseService: CourseService,
        private route: ActivatedRoute,
        private router: Router) 
  

  // On start of the life cycle
  ngOnInit() 
    // get the current course id to use it on the html file
    const id = +this.route.snapshot.paramMap.get('id');

    // set curretn course Id in the service to use it later
    this.courseService.setId(id);
    this.getCourse(id);
    

    // Get course detail by id
    getCourse(id: number) 
        this.courseService.getCourse(id).subscribe(
          course => this.course = course,
          error  => this.errorMessage = <any>error
        );
      


course-play.component

import  Component, OnInit, Input from '@angular/core';
import  ActivatedRoute, Router, Routes, NavigationEnd  from '@angular/router';
import  MatSidenavModule  from '@angular/material/sidenav';

import  ICourse  from '../course';
import  CourseService  from '../course.service';


// Couse-play decorator
@Component(
  selector: 'lg-course-play-course-play',
  templateUrl: './course-play.component.html',
  styleUrls: ['./course-play.component.sass']
)

export class CoursePlayComponent implements OnInit 
  errorMessage: string;
  course: ICourse;
  courseId: number;

  constructor(private courseService: CourseService,
      private route: ActivatedRoute,
      private router: Router) 
         courseService.courseId$.subscribe( courseId => 
           this.courseId = courseId;
         )
    

    // On start of the life cycle
    ngOnInit() 
        // get the current segment id to use it on the html file
        const segment_id = +this.route.snapshot.paramMap.get('segment_id');

        console.log(this.courseId);
        this.getCourse(this.courseId);
      


      // Get course detail by id
      getCourse(id: number) 
          console.log(id);
          this.courseService.getCourse(id).subscribe(
            course => this.course = course,
            error  => this.errorMessage = <any>error
          );
        


【问题讨论】:

您想在localStorage 中存储什么数据?当你想存储东西时,使用localStorage.setItem("Your_key", JSON.stringify(yourValue)),当你想检索它时,使用JSON.parse(localStorage.getItem("Your_key")) 我想保存 courseId。在哪里保存? your_key 是什么意思?其名称?以及在哪里使用它?在我从中获取的服务或组件中? localStorage 是一个键值对,所以我们用名称your_key 存储它,这意味着当我们要检索它时,我们还必须使用your_key。你可以使用任何你喜欢的字符串。我建议在服务内拨打localStorage。每次更改时保存 courseId 【参考方案1】:

首先,setId() 方法中有一个错误 - 它必须将课程 ID 的值作为参数而不是主题。

您需要在对主题调用next() 后立即更新本地存储,并在服务的构造函数中从存储中重新加载保存的数据。例如,

const COURSES_IN_STORAGE = 'courses_in_storage';

@Injectable()
export class CourseService
...
  courseIdState: string;

  // This method is invokes by the component  
  setId(courseIdValue: string) 
    this.courseId.next(courseIdValue);
    localStorage.setItem(COURSES_IN_STORAGE, courseIdValue);
  

 constructor() 
    this.courseIdState = localStorage.getItem(COURSES_IN_STORAGE) || ; 
  

【讨论】:

【参考方案2】:

您可以通过以下方式将数据保存到本地存储中:

localStorage.setItem('变量名', JSON.stringify('要保存的数据'));

并通过以下方式从本地存储中取回数据:

this.anyvariable= JSON.parse(localStorage.getItem('savedvariablename'));

关于本地存储就是这样:

【讨论】:

以上是关于Angular 6 BehaviorSubject 使用 LocalStorage的主要内容,如果未能解决你的问题,请参考以下文章

Angular 7 rxjs BehaviorSubject 发出重复值

Angular 中的 Subject vs BehaviorSubject vs ReplaySubject

ERROR 错误:未捕获(承诺中):TypeError:i.BehaviorSubject 不是 Angular 10 s-s-r 中的构造函数

RxJS - BehaviorSubject,onComplete 未调用

node_modules 没有导出的成员 'BehaviorSubject'

BehaviorSubject 和条件组件显示