首页 文章

获取不正确的offsetWidth和offsetHeight值

提问于
浏览
6

这是我的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">
</div>

零件

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;
}

问题是每次加载的打印值都不同 . 我猜这个问题是由于浏览器还没有完成加载div . 你知道这个解决方案是什么吗?

2 回答

  • 2

    您可以使用检测大小更改

    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 内使用它并刷新偏移量 . 您可以更具体,只检测一些突变,然后才能提取偏移量 .

    more info :

    doc:https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

    兼容性:https://caniuse.com/#feat=mutationobserver

    Demo

    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>
    
  • 1

    您必须在渲染周期后安排对'offsetWidth'的调用,角度执行在微任务队列结束时绘制,因此您可以尝试 setTimeout(..., 0) 或在zonejs之外运行 Promise.resolve().then(...) . 希望能帮助到你 .

相关问题