【问题标题】:Angular2+ two-way binding to cause sibling to update on initialisationAngular2 +双向绑定导致兄弟在初始化时更新
【发布时间】:2018-12-07 13:01:49
【问题描述】:

我有 3 个组件结构。父组件有 2 个数组,allItems 和 pagedItems。 Pager 组件具有 item 的输入值和 pagedItems 的双向绑定。表格组件具有分页项的输入值。

组件示例

export class Table {

    @Input()
    pagedItems: any[] = [];
    constructor() { }
}

export class Pager {
    items: any[];

    @Input()
    set items(value: any) {
        this._items = value;
        this.setPage(this.currentPage);
    }

    get items() {
        return this._items;
    }

    _pagedItems: any[];

    @Input()
    get pagedItems() {
        return this._pagedItems;
    }

    @Output() pagedItemsChange = new EventEmitter();

    set pagedItems(value) {
        this._pagedItems = value;
        this.pagedItemsChange.emit(this._pagedItems);
    }

    setPage(page: number) {

        this.pager = this.pagerService.getPager(this.items.length, page, parseInt(this._pageSize));
        this.pagedItems = this.items.slice(this.pager.startIndex, this.pager.endIndex + 1);

    }
}

export class Parent {

    allItems: any[] = [];
    pagedItems: any[] = [];

    ngOnInit() { this.getData(); }
    getData() {
        ajaxcall.then(data => {
            this.allItems = data;
        })
    }
}

下面是 HTML 结构的示例:

<table class="col-12 col-md-12 col-lg-12 main-tbl pl-0 pr-0"
                                 [pagedItems]="pagedItems"
                                ></tbl-img-procurer-browser>

        <pager class="col-12 col-md-12 col-lg-12 main-tbl pl-0 pr-0"
               [items]="allItems" [(pagedItems)]="pagedItems"
         ></pager>

当我打开父组件时,它会调用 getData() 方法。这从服务器获取数据并将其放入 allItems 数组。现在 pager 获取数组并对其进行分页。并填充 pagedItems 数组。现在应该发生的是表格组件获取分页项并呈现它们。但实际发生的是表永远不会获取数据。现在,如果我更改寻呼机上的页面,表格会突然获取数据并开始显示它。为什么初始化的时候取不到数据?

编辑:

起初我认为这是不必要的信息,但根据 Mickers 给出的答案,我认为这是必要的。

我有一个额外的组件来处理表格的搜索表单。这个组件 onInit 创建一个事件,父级侦听并使用来自该事件的数据来执行 getData() ajax 调用。我不知道我是否可以在这里使用 resolve Guard。

export class filter{

@Output("onSubmit") onSearch: EventEmitter<SearchInput> = new EventEmitter<SearchInput>();

ngOnInit(){
    this.onSubmit();
    this.onSubmit();
  }

getSearchInput(){
    let searchInput: SearchInput = new SearchInput(
      //collects data from search form.
    );

    return searchInput;
  }

onSubmit() {
    this.onSearch.emit(this.getSearchInput());
  }

}

所以结构实际上是:

 <filter (onSubmit)="getData($event)"></filter>
 <table class="col-12 col-md-12 col-lg-12 main-tbl pl-0 pr-0"
                                     [pagedItems]="pagedItems"
                                    ></tbl-img-procurer-browser>

            <pager class="col-12 col-md-12 col-lg-12 main-tbl pl-0 pr-0"
                   [items]="allItems" [(pagedItems)]="pagedItems"
             ></pager>

【问题讨论】:

  • 您没有使用组件,因此这无助于我的建议,即使用 ngOnInit 生命周期挂钩来确保您的 html 已呈现。有没有机会使用解析器防护?这同样需要一个组件,但解析器会在组件加载之前触发并加载您的数据。
  • @Mickers 我可能可以。你能举个例子来说明你将如何在这里使用它吗?

标签: angular angular2-template angular2-changedetection


【解决方案1】:

我可以举例说明如何实现这一点。

首先您需要更新您的路由器(您必须使用路由器才能进行此修复):

const HOME_ROUTE: Routes = [
  {
    path: 'home', // replace this with your route and component name
    component: HomeComponent,
    resolve: [HomeResolver] // this is where you implement the guard
  }
];

export default HOME_ROUTE;

这是守卫的外观示例:

@Injectable()
export class HomeResolver implements Resolve<string> {
  constructor(private router: Router) {}

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<string> {
    console.log('home resolver fired');
    return of('true');
  }
}

更新您的组件以提取数据:

ngOnInit() {
    this.route.data.subscribe(({ str}) => {
        this.message= str;
    });
}

我希望这会为您指明正确的方向。

【讨论】:

  • 更多信息请参考article
  • 但是如果其中一个子组件在其 ngOnInit 钩子中触发 getData 事件,这会起作用吗?据我了解,如果获取数据从父级触发,这将起作用。如果您查看问题,我对其进行了编辑,并添加了更多详细信息。我不知道守卫在这种情况下是否可以工作。
  • 一旦页面加载完毕,解析器就完成了它的工作。如果在子组件的生命周期中有额外的调用,那么它们应该由父组件处理。父母可以根据需要更新孩子。 Angular 应该足够聪明,只重新渲染有变化的子组件。
  • 这是容器组件样式的一部分,其中父级只是一个容器,用于进行服务器调用并更新组件或子级。容器组件中几乎没有逻辑或 HTML。它只是处理数据并将其向下传递。
  • 那么有没有好办法让子组件从头开始更新循环呢?目前在过滤器组件中,我调用了两次 onSubmit。第一次它获取所有内容但不更新整个 DOM,第二次它也更新 DOM。这很糟糕,因为它执行了两次 ajax 调用,但至少它给出了结果。
猜你喜欢
  • 2016-04-14
  • 1970-01-01
  • 2017-02-06
  • 2017-04-22
  • 1970-01-01
  • 2016-11-12
  • 2017-07-09
  • 2015-08-08
  • 1970-01-01
相关资源
最近更新 更多