如何让我的组件在 Angular 2 中检测它们自己的高度和宽度?
How can I get my components to detect their own height and width in Angular 2?
我决定深入研究将 CSS 网格与 Angular 结合使用,我正在做的其中一件事是允许组件动态生成与根据自己的测量得出的黄金比例。我已经将 @ViewChild
与添加 #someName
到我想调用的元素结合使用,所以我认为相同的主体将适用于定位父容器或其自身。我遇到过 ElementRef
和 TemplateRef
,但它们似乎只针对组件的子组件。
在很多情况下,我可以通过在父组件中使用 @ViewChild
并通过 @Input
将大小发送到子组件来很好地实现这一点。我对这个想法的唯一看法是在 <router-outlet>
中加载组件的实例。有什么方法可以实现吗?
原答案
事实上,如果你想让一个组件或指令知道它的宿主或父元素的细节,你需要一个 ElementRef
,将引用传递给组件的方法是通过依赖注入。
考虑一个名为 SomeParentComponent
的组件和另一个组件,它是它的子组件:
@Component({
selector: 'some-child'
..
})
export class SomeChildComponent {
constructor( @Self() private element: ElementRef ) {}
}
通过使用 @Self
装饰器并在构造函数中注入 ElementRef
,您可以获得对 <some-child>
元素的引用,因此您可以查询 element.nativeElement
喜欢 offsetHeight
和 offsetWidth
.
但是,当您查询这些属性时请注意,因为如果您在 some-child
的模板中使用 <ng-content>
投影内容,或者您正在实例化另一个组件,您将得到不同的结果不同生命周期挂钩中这些属性的值,因为例如,投影内容仅从 ngAfterContentInit
开始存在。
您还可以通过将父组件或组件树中的任何组件注入到构造函数中来获取父组件的引用:
@Component({
selector: 'some-child'
..
})
export class SomeChildComponent {
constructor( @Host() private someParent: SomeParentComponent ) {}
}
通过这种方式,您可以访问 SomeParentComponent
的 class 定义,使用甚至修改其 public 属性。
尽管 @Host
和 @Self
装饰器的使用都是可选的,但它使您作为组件的依赖项传递的内容更加清晰。
编辑 2017 年 11 月 17 日
为了访问注入的 ElementRef
的属性,有几种选择,您可以使用值访问器或只是一个普通的 class 方法:
@Component({...})
export class SomeChildComponent implements OnInit {
// Using a getter accesor for each property
get height(): number {
return this.element.offsetHeight;
}
get width(): number {
return this.element.offsetWidth;
}
// Using a getter accesor for both properties
get dimensions(): { width: number, height: number } {
return { width: this.element.offsetWidth, height: this.element.offsetHeight }
}
constructor( @Self() private element: ElementRef ) {}
ngOnInit() {
console.log( this.height ); // this.element.nativeElement.offsetHeight
console.log( this.width ); // this.element.nativeElement.offsetWidth
console.log( this.dimensions ); // { width: this.element.offsetWidth, height: this.element.offsetHeight }
console.log( this.getDimensions() ); // { width: this.element.offsetWidth, height: this.element.offsetHeight }
}
// Using a class method
getDimensions() {
return { width: this.element.offsetWidth, height: this.element.offsetHeight }
}
}
我决定深入研究将 CSS 网格与 Angular 结合使用,我正在做的其中一件事是允许组件动态生成与根据自己的测量得出的黄金比例。我已经将 @ViewChild
与添加 #someName
到我想调用的元素结合使用,所以我认为相同的主体将适用于定位父容器或其自身。我遇到过 ElementRef
和 TemplateRef
,但它们似乎只针对组件的子组件。
在很多情况下,我可以通过在父组件中使用 @ViewChild
并通过 @Input
将大小发送到子组件来很好地实现这一点。我对这个想法的唯一看法是在 <router-outlet>
中加载组件的实例。有什么方法可以实现吗?
原答案
事实上,如果你想让一个组件或指令知道它的宿主或父元素的细节,你需要一个 ElementRef
,将引用传递给组件的方法是通过依赖注入。
考虑一个名为 SomeParentComponent
的组件和另一个组件,它是它的子组件:
@Component({
selector: 'some-child'
..
})
export class SomeChildComponent {
constructor( @Self() private element: ElementRef ) {}
}
通过使用 @Self
装饰器并在构造函数中注入 ElementRef
,您可以获得对 <some-child>
元素的引用,因此您可以查询 element.nativeElement
喜欢 offsetHeight
和 offsetWidth
.
但是,当您查询这些属性时请注意,因为如果您在 some-child
的模板中使用 <ng-content>
投影内容,或者您正在实例化另一个组件,您将得到不同的结果不同生命周期挂钩中这些属性的值,因为例如,投影内容仅从 ngAfterContentInit
开始存在。
您还可以通过将父组件或组件树中的任何组件注入到构造函数中来获取父组件的引用:
@Component({
selector: 'some-child'
..
})
export class SomeChildComponent {
constructor( @Host() private someParent: SomeParentComponent ) {}
}
通过这种方式,您可以访问 SomeParentComponent
的 class 定义,使用甚至修改其 public 属性。
尽管 @Host
和 @Self
装饰器的使用都是可选的,但它使您作为组件的依赖项传递的内容更加清晰。
编辑 2017 年 11 月 17 日
为了访问注入的 ElementRef
的属性,有几种选择,您可以使用值访问器或只是一个普通的 class 方法:
@Component({...})
export class SomeChildComponent implements OnInit {
// Using a getter accesor for each property
get height(): number {
return this.element.offsetHeight;
}
get width(): number {
return this.element.offsetWidth;
}
// Using a getter accesor for both properties
get dimensions(): { width: number, height: number } {
return { width: this.element.offsetWidth, height: this.element.offsetHeight }
}
constructor( @Self() private element: ElementRef ) {}
ngOnInit() {
console.log( this.height ); // this.element.nativeElement.offsetHeight
console.log( this.width ); // this.element.nativeElement.offsetWidth
console.log( this.dimensions ); // { width: this.element.offsetWidth, height: this.element.offsetHeight }
console.log( this.getDimensions() ); // { width: this.element.offsetWidth, height: this.element.offsetHeight }
}
// Using a class method
getDimensions() {
return { width: this.element.offsetWidth, height: this.element.offsetHeight }
}
}