scrollHeight的替代DOM属性

VJP*_*Paz 0 html javascript autoresize knockout.js

有没有其他方法可以在不使用scrollHeight的情况下获取某个HTML元素的内部高度?

事情是,我有一个包含100条记录的表,在每条记录中,我使用height = 0然后height = scrollHeight调整列中某个textarea的大小.

问题是IE执行scrollHeight至少20~50ms取决于大小而我有大约100条记录.这意味着,仅仅为IE渲染所有记录,只需加载100条记录就需要6秒以上,如果我需要加载100条记录呢?这会破坏我的网站.

所以我问是否有任何替代scrollHeight或者你可以提供任何替代代码来调整textarea的大小.

谢谢你的进步,

UPDATE

这是我从IE UI响应中得到的 在此输入图像描述

更新2

第二张图片:正如你在下面的图片中看到的那样,为什么IE在获取某个元素(textarea)的scrollHeight方面很慢的问题是因为它计算整个布局(html主体)而不是仅获取该特定的scrollHeight元素(textarea元素)

在此输入图像描述

Ama*_*dan 5

听起来你是一行一行,阅读scrollHeight然后设置height.这是非常昂贵的,因为写入后的每次读取都会触发回流以便给出准确的答案(因为写入可能会改变页面上会影响读取值的内容).这不需要height=scrollHeight时间; 它是必要的回流,以便它做到这一点.

layout (write height of all: 0)

reflow
read scrollHeight
write height

reflow (!)
read scrollHeight
write height

reflow (!)
read scrollHeight
write height
...

reflow (!)
paint
Run Code Online (Sandbox Code Playgroud)

(或者你可能height在每次迭代中都设置为0;这并不重要,因为连续写入不会触发重排.)

相反,尝试批量执行此操作.将所有scrollHeight值读入数组; 然后,当你拥有它们时,将它们全部设置好.通过这种方式,您只能获得两次回流:一次开始阅读,一次完成代码并且浏览器需要显示页面,因为只要您只是阅读或只是写作,就不会有回流需要 - 只有当你从写作到阅读价值.

layout (write height of all: 0)

reflow
read scrollHeight
read scrollHeight
...
write height
write height

reflow
paint
Run Code Online (Sandbox Code Playgroud)

编辑:这是一个黑客; 我还没有在Knockout那么好.但作为可能的最小例子,如果你不能以任何其他方式做到,它可能会做.您可能想要运行它并延伸到"完整页面",否则您将无法看到任何内容:)

var vm = {
  list: ko.observableArray(["foo", "bar\nbaz", "1\n2\n3\n4"])
};

var updatedHeights;

ko.bindingHandlers.autoresizeStart = {
  update: function(elem, valueAccessor) {
    var data = ko.utils.unwrapObservable(valueAccessor());
    console.log("start update; setting updateHeights to []");
    updatedHeights = [];
  }
};
ko.bindingHandlers.autoresize = {
  update: function(elem, valueAccessor) {
    console.log("mid update;", elem, "is updated, so let's remember its scrollHeight");
    updatedHeights.push([elem, elem.scrollHeight]);
  }
};
ko.bindingHandlers.autoresizeEnd = {
  update: function(elem, valueAccessor) {
    var data = ko.utils.unwrapObservable(valueAccessor());
    console.log("end update; lets set heights for all updated elements:");
    updatedHeights.forEach(function(elemWithHeight) {
      console.log("  ", elemWithHeight[1], elemWithHeight[0]);
      elemWithHeight[0].style.height = elemWithHeight[1] + "px";
    });
    console.log("all done :)");
  }
};

ko.virtualElements.allowedBindings.autoresizeStart = true;
ko.virtualElements.allowedBindings.autoresizeEnd = true;


ko.applyBindings(vm);

setTimeout(function() {
  vm.list.push("a\nb\nc\nd\ne\nf\ng");
}, 1000);
Run Code Online (Sandbox Code Playgroud)
<!-- results pane console output; see http://meta.stackexchange.com/a/242491 -->
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>

<!-- ko autoresizeStart: list --><!-- /ko -->
<ul data-bind="foreach: list">
  <li >
    <textarea data-bind="text: $data, autoresize: $data"></textarea>
  </li>
</ul>
<!-- ko autoresizeEnd: list --><!-- /ko -->
Run Code Online (Sandbox Code Playgroud)