Angular 6 @Viewchild无法使用延迟加载

时间:2018-12-05 07:44:40

标签: javascript angular angular6 lazy-loading

这是我的代码,显示错误,无法读取未定义的属性标题。

父组件

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(…)

3 个答案:

答案 0 :(得分:11)

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

ParentComponent

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 Demo供您参考(检查控制台)

如果您要访问在父组件的<router-outlet>下呈现的ChildComponent,可以通过使用(激活)路由器出口的受支持属性来实现:

  

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

     

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(event)控制台上,供您访问

答案 1 :(得分:3)

那不是应该的工作方式。如果您的ChildComponent模板中有ParentComponent标签,您将只能在<app-child></app-child>中获得ParentComponent。 >

类似这样的东西:

...

<app-child></app-child>

...

但是由于您使用子路由,并且ChildComponent将加载到router-outlet的{​​{1}}中,因此您将无法使用ParentComponent < / p>

PS:您只能在ViewChild内访问它,因为ngAfterViewInit仅在视图加载后才可以安全地实例化:

ViewChild

以下是您的参考资料Working Sample StackBlitz,它说明了两种情况下的情况。

PS::要通过路由获得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); } } 中的ChildComponent属性,您必须使用ParentComponent或以QueryParam的形式在路由中传递ChildProperty,并使用SharedService

在您的ParentComponent中读取它

更新:

使用路径查询参数共享数据:

尽管这没有多大意义,但是在您的ActivatedRoute中,您可以拥有一个链接,该链接将通过ChildComponent属性作为title传递用户到ChildComponent 。像这样:

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的{​​{1}},即可通过在其上调用private方法将其显示为BehaviorSubject。可以通过暴露一个方法(Observable)来设置其值,该方法实际上将使用更新后的asObservable值调用setChildProperty方法:

next

然后可以将其注入到childPropertyimport { 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); } } 中:

ParentComponent中设置值:

ChildComponent

然后在您的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);
  }

}

答案 2 :(得分:2)

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