这是我的angular2代码。
模板
<div #picker class="slider">
<div class="slider-track">
<div #sliderSelectionEl class="slider-selection"></div>
<div #sliderHandle1 class="slider-handle"></div>
<div #sliderHandle2 class="slider-handle"></div>
</div>
<div #tooltipEl class="tooltip">
<div class="tooltip-arrow"></div>
<div #tooltipInner class="tooltip-inner"></div>
</div>
<input type="text" class="span2" value="" id="sl2"><br/>
</div>
&#13;
元器件
import {Component, OnInit, Input, ViewChild, ElementRef, Renderer} from '@angular/core'; export class SliderComponent implements OnInit { @ViewChild('picker') picker: ElementRef; constructor(private renderer: Renderer, private el: ElementRef) { } ngAfterViewInit() { this.renderer.setElementClass(this.picker.nativeElement, 'slider-horizontal', true); console.log(this.picker.nativeElement.offsetWidth); console.log(this.picker.nativeElement.offsetHeight); } }
.slider-horizontal {
width: 210px;
height: 20px;
}
&#13;
问题是每次加载时打印值都不同。我猜这个问题是由于浏览器还没有完成加载div。你知道这是什么解决方案吗?
答案 0 :(得分:3)
您必须在渲染周期之后安排对“ offsetWidth”的调用,在微任务队列的末尾执行angular执行绘制,因此您可以尝试setTimeout(..., 0)
或在zonejs之外运行Promise.resolve().then(...)
。希望对您有所帮助。
答案 1 :(得分:1)
您可以使用
检测尺寸变化MutationObserver
此新api的最大受众可能是 编写JS框架,[...]另一个用例是您正在使用操纵DOM的框架并需要对此做出反应的情况 修改有效(并且没有setTimeout hacks!)。
在这里,您可以使用它来检测元素的变化:
// select the target node
var target = document.querySelector('#some-id'); // or
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation.type);
});
});
// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true }
// pass in the target node, as well as the observer options
observer.observe(target, config);
// later, you can stop observing
observer.disconnect();
对于您的情况,您可以在ngAfterViewInit
内使用它并刷新偏移量大小。您可以更具体一些,只检测一些突变,然后才提取偏移。
更多信息:
doc:https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
兼容性:https://caniuse.com/#feat=mutationobserver
演示:
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation);
if(mutation.attributeName == 'class') // detect class change
/*
or if(mutation.target.clientWidth == myWidth)
*/
showOffset(mutation.target);
observer.disconnect();
});
});
var config = { attributes: true}
var demoDiv = document.getElementById('demoDiv');
var logs = document.getElementById('logs');
// wait for document state to be complete
if (document.readyState === "complete") {
ngAfterViewInit();
}
document.onreadystatechange = function () {
if (document.readyState === "complete") {
ngAfterViewInit();
}
}
// observe changes that effects demoDiv + add class
function ngAfterViewInit(){
observer.observe(demoDiv, config);
demoDiv.classList.add('slider-horizontal');
}
// show offsetWidth + height.
// N.B offset width and height will be bigger than clientWidth because I added a border. If you remove the border you'll see 220px,20px
function showOffset(element){
offsetMessage = "offsetWidth:" + demoDiv.offsetWidth + " offsetHeight: " + demoDiv.offsetHeight;
console.log(offsetMessage);
logs.innerHTML = offsetMessage;
}
.slider-horizontal {
border: 2px solid red;
width: 210px;
height: 20px;
background: grey;
}
<div id='demoDiv'> I am a demo div </div>
<div style="margin-top: 20px;"> logs : <span id='logs' style=" padding: 5px; border: 1px solid black"></span></div>
答案 2 :(得分:0)
为了获得正确的偏移值,可以使用:带有AfterContentChecked接口的ngAfterContentChecked。
每次更改检测运行后都调用此方法。因此,在此方法内部使用一个标志(或计数器)和setTimeOut:
if (this.counter <= 10) {
// this print offsetwidth of my element
console.log('mm ' + this.container.nativeElement.offsetWidth);
// setTimeOut allow to run another changedetection
// so ngAfterContentChecked will run again
setTimeout(() => { }, 0);
//you could use a counter or a flag in order to stop getting the right width
this.counter++;
}
希望有帮助!随时发表评论