永远不要在DOM中存储中间程序状态?

时间:2010-10-18 12:36:33

标签: javascript html

前几天我设法遇到this funny bug,过快的DOM修改导致整个Internet Explorer崩溃。所以我在想,为什么我甚至会设置这些值,如果我以后要改变它们呢? (修改是非常不可预测的,所以完全避免这种情况是不可能的)

有些背景,我的网站更像是一个游戏/应用程序,并且有很多自定义元素等。性能是关键并且四处移动并且修改对象应该快速,平滑且没有闪烁。在一次迭代中,大量的对象可以修改它们的状态。

我的应用程序中的对象现在遵循与此模式类似的内容。 domElement是DOM中使用的实际元素,使用document.createElement或getElementById创建。

function SetWidth(w) {
  this.width = w;
  this.domElement.style.width = w + "px";
}

一个对象有很多样式而不仅仅是宽度,只是为了简化事情。这个现在很好用,但是如果我出于某种原因在一个“程序循环”中将一个对象的宽度设置为两次。这意味着DOM将被修改两次,但它只是应该显示的第二个状态。在大多数新浏览器中,这没有什么区别,因为在所有用户javascript完成之前不会呈现页面。但在某些浏览器中,您可以随时获得无法预测的更新。即使没有明显的变化,它是否会影响性能?

另一个问题是,某些元素依赖于附加到DOM,然后才能设置/获取某些属性,您可以使用下面的模式更轻松地避免这些属性。

我想要做的是回到老式的渲染循环模式。 所以上面的对象看起来像这样:

function SetWidth(w) {
  this.width = w;
  this.stateChanged = true;
}
function Render() {
  if(this.stateChanged)
      this.domElement.style.width = this.width + "px";
}

完成“程序循环”后,您只需遍历每个对象以“渲染”它们(或使用一些更复杂的结构来跟踪所有修改过的对象)。

对我而言,这似乎打败了拥有DOM的整个目的,因为你基本上正在重新发明现有的东西,但有时感觉它不能正常工作,所以你必须推出自己的版本。

有没有人使用类似的东西,是否值得?优缺点都有什么?还有什么我需要考虑的?还应考虑添加和删除对象以及管理z-index。

1 个答案:

答案 0 :(得分:0)

需要注意的一件事是,如果您请求依赖于布局的属性值,浏览器将重新计算布局以获取值,这可能需要很长时间。所以“this.style.width ='80px'”会很快,但是“this.style.width ='80px'; var wid = this.clientWidth;”需要更长时间。当然,如果你使用上面的setWidth / render模式,你将无法获得值 clientWidth直到渲染阶段之后。

setWidth / render模式对于您的用例是合理的,但是我创建了一个子对象来保存挂起的布局值,而不是直接将它们存储在'this'对象上。如果在渲染步骤结束时清空/重新创建子对象,则不需要存储单独的stateChanged变量,子对象中属性的存在可以用于此目的。