如何在Angular中获取DOM元素的样式?

时间:2017-05-19 05:23:15

标签: angular

我知道你可以使用ngStyle来设置元素的样式。但是我如何获取元素的样式(即浏览器呈现的默认样式)?

此代码不起作用,但表达了我正在尝试做的事情:

<p>TEXT</p>
width of TEXT element is {{textElement.width}}
height of TEXT element is {{textElement.height}}

我希望p元素正常呈现(但是浏览器想要,而不是告诉它宽度或高度)。但是,我想知道渲染的宽度和高度是多少。如何绑定东西以捕获它?

编辑:有些人问我想要做什么宽度和高度。我想做的是这样的事情:

<p *ngIf="!isEditing">{{myText}}</p>
<textarea *ngIf="isEditing" [(ngModel)]="myText"></textarea>

默认情况下,显示p而textarea不显示。如果用户进入编辑模式,则p将被textarea替换。我想设置textarea的宽度和高度以匹配p,因此过渡看起来无缝。有更好的方法吗?

3 个答案:

答案 0 :(得分:7)

最好的方法是使用一个指令,通过该指令可以访问应用此指令的本机DOM元素。然后你可以等到DOM在AfterViewInit钩子中呈现并使用getComputedStyle方法来获取所有计算出的样式。

import { Directive, ElementRef } from '@angular/core';

@Directive({
  selector: '[style-getter]'
})

export class StyleGetter {
  constructor(public el: ElementRef) {}

  ngOnChanges() {
    setTimeout(() => {
      let styles = getComputedStyle(this.el.nativeElement);
      console.log(styles.offsetWidth);
    })
  }

  ngAfterViewInit() {
    let styles = getComputedStyle(this.el.nativeElement);
      console.log(styles.offsetWidth);
  }
}

你也应该挂钩ngOnChanges钩子,因为在输入绑定改变时经常会重新呈现DOM。您可以使用setTimeout等待所有样式计算并呈现DOM。

您还必须使用offsetWidth代替width,因为:

  

offsetWidth返回计算元素的宽度,而el.style.width   只返回由javascript和。在element.style中定义的width属性   不反映真实元素的维度。

了解更多here

答案 1 :(得分:1)

最好的方法是不要这样做。

浏览器在HTML和CSS的驱动下进行生活布局。它们共同提供了丰富的控件布局功能,包括媒体查询,flexbox等等。

获取元素的高度然后在那里调整这个东西或者将这个东西移到那里是一个滑坡。在您了解它之前,您将最终重新创建并重做浏览器旨在为您完成的大部分布局工作。

如果你真的想要达到这个高度,那么当然有办法做到这一点,正如其他答案中所提到的那样。但是,在你开始这条道路之前,你应该确保你真的想要并且需要。

如果你提供一个更具体的例子,一旦你检索它你想要做什么高度,这里的人可能会建议很多方法来完成同样的事情,没有很多Angular / TS代码。

要使用替换<p>的textarea完成您想要的操作,您可以尝试这样做:

let editing = false;

function toggle() {
  document.getElementById('div').classList.toggle('editing', editing = !editing);
}
div { border: 1px solid gray; position: relative; }

textarea { 
  display: none; 
  height: 100%; width: 100%; 
  position: absolute; top: 0; left: 0; 
}

.editing textarea { display: block; }
.editing p { visibility: hidden; }
<p><button onclick="toggle()">Toggle editing</button></p>

<div id="div">
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
  
  <textarea></textarea>

</div>

我确信你可以通过查看代码来弄清楚,方法是将ptextarea放在div之内。 div的大小将由p的大小决定。 textarea绝对定位为与div完全对齐。处于编辑模式时,p设置为visibility: hidden;,其在布局中保持其位置/大小,但隐藏它,textarea设置为display: block;所以它显示出来了。

改编自Angular,并使用相同的CSS,这将是:

// component 
editable = false;

// template
<p><button (click)="editable = !editable">Toggle editing</button></p>

<div id="div" [class.editable]="editable">
  <p>{{myText}}</p>
  <textarea [(ngModel)]="myText"></textarea>
</div>

答案 2 :(得分:1)

这也可以使用@ViewChild

完成

stackblitz链接:https://stackblitz.com/edit/angular-playground-jzgein

component.ts:

import {Component, ElementRef, Input, OnInit, ViewChild} from '@angular/core';

@Component({
  selector: 'my-app',
  styleUrls: ['./app.component.scss'],
  templateUrl: './app.component.html',
})
export class AppComponent implements OnInit {
   @ViewChild('viewChildHook', {static: true}) viewChildHook: ElementRef;

ngOnInit(){
      const value = getComputedStyle(this.viewChildHook.nativeElement).getPropertyValue('--my-variable-name');
      console.log("value", value);

}

}

component.html:

<div #viewChildHook class="html-dom-element">
    aaaaaaaaaaaaaaaaaaaaaa
    bbbbbbbbbbbbbbbbbbbbbb
    cccccccccccccccccccccc
</div>

component.scss:

.html-dom-element{
  --my-variable-name: 300px;
    width: var(--my-variable-name);
}