Angular框架专题

Angular框架中的父子组件通信传递异步的数据接收值异常的问题

2021-12-08  本文已影响0人  听书先生

父组件传递给子组件的值为async data异步数据,子组件接收的过程中可能就会出现问题,子组件接收不到父组件传递过来的值,此时视图也无法进行渲染。

import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { Post, GroupPosts } from '../post.interface';

// 定义接口
export interface Post {
    title: string;
    category: string;
}
export interface GroupPosts {
    category: string;
    posts: Post[];
}
@Component({
    selector: 'exe-message',
    template: `
    <div class="list-group">
        <div *ngFor="let group of groupPosts;" class="list-group-item">
            <h4>{{ group.category }}</h4>
            <ul>
                <li *ngFor="let post of group.posts">
                    {{ post.title }}
                </li>
            </ul>
        <div>
    </div>
    `
})
export class ExeMessageComponent implements OnInit {

    _data = [];

    @Input()
    set data(value: any) {
        this._data = value;
    }

    get data() {
        return this._data;
    }

    groupPosts: GroupPosts[] = [];

    ngOnInit() {
      this.groupPosts = this.groupByCategory(this.data);
    }

    ngOnChanges(changes: SimpleChanges) {

    }

    groupByCategory(data: Post[]): GroupPosts[] {
        if (!data) return [];
        // 去重处理
        const categories = new Set(data.map(x => x.category));
        // 转为二维数组
        const result = Array.from(categories).map(x => ({
            category: x,
            posts: data.filter(post => post.category === x)
        }));
        return result;
    }
}
import { Component, OnInit, Input, SimpleChanges } from '@angular/core';
import { Observable, Observer } from 'rxjs';

// 定义接口
export interface Post {
    title: string;
    category: string;
}
export interface GroupPosts {
    category: string;
    posts: Post[];
}
@Component({
    selector: 'exe-bloggers',
    template: `
        <h1>{{ blogger }}</h1>
        <div>
            <exe-message [data]="posts"></exe-message >
        </div>
    `
})
export class KeysComponent implements OnInit {

    blogger = 'catalogue';
    posts: Post[] = [];

    ngOnInit() {
        this.getPosts().subscribe(posts => this.posts = posts);
    }

    getPosts(): Observable<Post[]> {
        return Observable.create((observer: Observer<Post[]>) => {
            setTimeout(() => {
                const posts = [
                    { "title": "containing a catalogue", "category": "react" },
                    { "title": "and an agreement.", "category": "vue" },
                    { "title": "show that we have sent", "category": "react" },
                    { "title": "gives a full description of each product", "category": "angular" },
                    { "title": "Topshop has coined an online category ", "category": "react" },
                    { "title": "The catalogue gives a full description", "category": "vue" }
                ];
                observer.next(posts);
            }, 2000);
        })
    }
}
image.png

根据结果来看,子组件并未接收到,获取的值是一个空数组。

2、解决方案
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { Post, GroupPosts } from '../post.interface';

// 定义接口
export interface Post {
    title: string;
    category: string;
}
export interface GroupPosts {
    category: string;
    posts: Post[];
}
@Component({
    selector: 'exe-message',
    template: `
    <div class="list-group">
        <div *ngFor="let group of groupPosts;" class="list-group-item">
            <h4>{{ group.category }}</h4>
            <ul>
                <li *ngFor="let post of group.posts">
                    {{ post.title }}
                </li>
            </ul>
        <div>
    </div>
    `
})
export class ExeMessageComponent implements OnInit {

    _data = [];

    @Input()
    set data(value: any) {
        this._data = value;
    }

    get data() {
        return this._data;
    }

    groupPosts: GroupPosts[] = [];

    ngOnInit() {
      this.groupPosts = this.groupByCategory(this.data);
    }

    ngOnChanges(changes: SimpleChanges) {
      console.log(changes)
      if (changes['data']) {
         this.groupPosts = this.groupByCategory(this.data);
      }
    }

    groupByCategory(data: Post[]): GroupPosts[] {
        if (!data) return [];
        // 去重处理
        const categories = new Set(data.map(x => x.category));
        // 转为二维数组
        const result = Array.from(categories).map(x => ({
            category: x,
            posts: data.filter(post => post.category === x)
        }));
        return result;
    }
}
image.png image.png
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
import { Post, GroupPosts } from '../post.interface';

// 定义接口
export interface Post {
    title: string;
    category: string;
}
export interface GroupPosts {
    category: string;
    posts: Post[];
}
@Component({
    selector: 'exe-message',
    template: `
    <div class="list-group">
        <div *ngFor="let group of groupPosts;" class="list-group-item">
            <h4>{{ group.category }}</h4>
            <ul>
                <li *ngFor="let post of group.posts">
                    {{ post.title }}
                </li>
            </ul>
        <div>
    </div>
    `
})
export class ExeMessageComponent implements OnInit {

  private _data$ = new BehaviorSubject<Post[]>([]);

  @Input()
  set data(value: Post[]) {
    this._data$.next(value);
  }

  get data(): Post[] {
    return this._data$.getValue();
  }


    groupPosts: GroupPosts[] = [];

    ngOnInit() {
      this._data$.subscribe((x: any) => {
        this.groupPosts = this.groupByCategory(this.data);
      });
    }
    
    ngOnDestroy(): void {
      // 如果数据不断的变化需要取消订阅
      this._data$.unsubscribe();
    }

    ngOnChanges(changes: SimpleChanges) { }

    groupByCategory(data: Post[]): GroupPosts[] {
        if (!data) return [];
        // 去重处理
        const categories = new Set(data.map(x => x.category));
        // 转为二维数组
        const result = Array.from(categories).map(x => ({
            category: x,
            posts: data.filter(post => post.category === x)
        }));
        return result;
    }
}
image.png
import { Observable, Observer } from 'rxjs';

  ...
 @Input() data: Observable<Post[]>; // 输入属性的类型是Observable

父组件User组件:

import { Observable, Observer } from 'rxjs';

 ...
posts: Observable<Post[]>;

如果想在模板中直接使用的话,可以使用AsyncPipe
在实际的开发场景中,需要参考业务层的应用方式,如果数据源只产生一次或者很少的次数的变化,那么可以直接考虑使用*ngIf指令,即当父组件异步数据获取到的时候才进行子组件的加载。如果是持续不断的改变,那么需要使用以上的方法去解决异步导致数据源无法获取的问题。

上一篇下一篇

猜你喜欢

热点阅读