3

我正在尝试在课程详细信息组件和课程播放组件之间传递数据。我使用了共享服务和 BehaviorSubject。数据通过服务正确传递到课程详细信息,当通过课程详细信息 html 页面转到课程播放 html 页面时,它工作得很好,但是当我刷新页面时,它使用的是我在服务。我需要找到一种方法让 id 在从 course-play 获得它后一直留在服务中,并在我获得另一个课程 id 时保持更新。这是我的代码:

课程.ts

export interface ICourse {
  course_id: number;
  title: string;
  autor: string;
  segments: ISegment[];
}

export interface ISegment {
  segment_id: number;
  unit_id: number;
  unit_title: string;
  name: string;
  type: string;
  data: string;
}

课程服务

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;
         )
      }

   // When we click the back button in browser
   onBack(): void {
     this.router.navigate(['/courses']);
   }

}

课程播放组件

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 segmentId = +this.route.snapshot.paramMap.get('id');
        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;
           )
        }

    // When we click the back button in browser
     onBack(): void {
       this.router.navigate(['/courses/:id']);
     }

}

4

2 回答 2

1

这是 BehaviorSubject 的默认行为。每当您刷新页面时,您都会从服务中获取默认 ID。如果您想获取更新后的 id,请将其存储在本地存储/cookie 中,并根据该值更新您的行为主题。

localStorage在更新 id 时存储价值:

localStorage.setItem(key, value);

从以下位置获取项目localStorage

localStorage.getItem(key);

当页面刷新时,您需要localStorage使用 next(); 从订阅者读取值并向订阅者发出值。 例子:

this.your_service.your_behavior_subject.next(value_from_localstorage);

您需要在全局组件 [app.component.ts] 中发出。所以它可以在您的应用程序中使用

于 2018-07-31T11:35:52.000 回答
0

需要将初始状态设置为从本地存储读取:

private myValue = JSON.parse(localStorage.getItem('myData')) as MyData;

然后播种商店:

public myData: BehaviorSubject<myData> = new BehaviorSubject(this.myValue);

要在没有本地存储时更改或播种,只需使用 .next 为其添加值。

于 2018-10-24T20:05:30.547 回答