繁体   English   中英

Angular 6 @Viewchild不支持延迟加载

[英]Angular 6 @Viewchild is not working with lazy loading

这是我的代码,给出错误无法读取属性标题undefined。

父组件

import { Child } from './child.component';
@Component({
  selector: 'parent',
})
export class ParentComponet implements OnInit, AfterViewInit {
 constructor(){}

  @ViewChild(Child) child: Child;

  ngAfterViewInit(){
    console.log("check data", this.child.title)
  }
}

和儿童组件是。

@Component({
      selector: 'child',
    })
    export class ChildComponet {

     public title = "hi"
     constructor(){}

    }

routing.module.ts就像

{
        path: "",
        component: ParentComponent,
        children: [
            {
                path: '/child',
                component: ChildComponent
            }
        ]
}

并且给出了错误

ERROR TypeError: Cannot read property 'title' of undefined(…)

我认为你缺少与创建组件相关的'template'或'templateUrl'

为父级

import { ChildComponent } from './child.component';    // {ChildComponent} not {Child} as we are referencing it to the exported class of ChildComponent

@Component({
   selector: 'parent',
   template: `<child></child>`
})
export class ParentComponet implements OnInit, AfterViewInit {...}

ChildComponent

@Component({
  selector: 'child',
  template: `<h1>{{ title }}</h1>`
})
export class ChildComponent {...}       // Be sure to spell it right as yours were ChildComponet - missing 'n'

根据用户对此主题的说明进行更新

已添加Stackblitz演示供您参考(检查控制台)

如果要访问在父组件的<router-outlet>下呈现的ChildComponent,可以通过利用(激活)router-outlet支持的属性来实现

每当实例化新组件时,路由器插座将发出激活事件

Angular Docs

ParentComponent的模板

@Component({
   selector: 'parent',
   template: `<router-outlet (activate)="onActivate($event)"></router-outlet>`
})
export class ParentComponent {

    onActivate(event): void {
        console.log(event);         // Sample Output when you visit ChildComponent url
                                    // ChildComponent {title: "hi"}

        console.log(event.title);   // 'hi' 
    }

}

结果将根据父母子女下的访问页面而有所不同

如果您访问Child1Component,您将获得其实例Child1Component {title: "hi"}

如果您访问Child2Component,您将获得其实例Child2Component {name: "Angular"}

然后,这些结果将反映在ParentComponent的onActivate(事件)控制台上,供您访问

这不是它应该如何工作。 你将只能得到ChildComponentParentComponent 只有当你有<app-child></app-child>标签在你ParentComponent模板。

像这样的东西:

...

<app-child></app-child>

...

但是,由于您正在使用子路由,并且ChildComponent将加载到您的ParentComponentrouter-outlet ,您将无法使用ViewChild访问它

PS:你只能在ngAfterViewInit访问它,因为ViewChild在加载View之后只能被认为是安全的实例化:

import { Component, OnInit, ViewChild } from '@angular/core';
import { ChildComponent } from '../child/child.component';
...

@Component({...})
export class ParentComponent implements OnInit {

  @ViewChild(ChildComponent) childComponent: ChildComponent;

  ...

  ngAfterViewInit() {
    console.log(this.childComponent);
  }

}

这是您的参考文献的工作示例StackBlitz ,它说明了两种情况下的情景。

PS:要使用Routing获取ParentComponentChildComponent属性,您必须使用SharedService或者您必须将路径中的ChildProperty作为QueryParam传递,并使用ActivatedRoute在ParentComponent中读取它

更新:

使用Route Query Params共享数据:

虽然这没有多大意义,但是在您的ChildComponent ,您可以拥有一个Link,它将用户路由到具有titleParam传递的title属性的queryParam 像这样的东西:

<a 
  [routerLink]="['/child']" 
  [queryParams]="{title: title}">
  Go To Child Route With Query Params
</a>

在您的ParentComponent中可以使用ActivatedRoute访问它,如下所示:

...
import { ActivatedRoute } from '@angular/router';
...

@Component({...})
export class ParentComponent implements OnInit {

  ...

  constructor(
    private route: ActivatedRoute,
    ...
  ) { }

  ngOnInit() {
    this.route.queryParams.subscribe(queryParams => {
      console.log('queryParams[`title`]', queryParams['title']);
    });
    ...
  }

  ...

}

使用SharedService

只需SharedService private BehaviorSubject创建一个SharedService ,通过在其上调用asObservable方法将其作为Observable公开。 可以通过公开一个方法( setChildProperty )来设置它的值,该方法本质上会使用更新的childProperty值调用next方法:

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';

@Injectable()
export class SharedService {

  private childProperty: BehaviorSubject<string> = new BehaviorSubject<string>(null);
  childProperty$: Observable<string> = this.childProperty.asObservable();

  constructor() { }

  setChildProperty(childProperty) {
    this.childProperty.next(childProperty);
  }

}

然后,您可以在ParentComponentChildComponent注入它:

ChildComponent设置值:

import { Component, OnInit } from '@angular/core';
import { SharedService } from '../shared.service';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {

  public title = "hi"

  constructor(private sharedService: SharedService) { }

  ngOnInit() {
    this.sharedService.setChildProperty(this.title);
  }

}

在您的ParentComponent获取值:

...
import { SharedService } from '../shared.service';

@Component({...})
export class ParentComponent implements OnInit {

  ...

  constructor(
    ...,
    private sharedService: SharedService
  ) { }

  ngOnInit() {
    ...
    this.sharedService.childProperty$.subscribe(
      childProperty => console.log('Got the Child Property from the Shared Service as: ', childProperty)
    );
  }

  ...

}

确保在parent.component.html模板中添加了<child></child>标记。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM