JS性能优化——减少DOM操作次数

需求:需要写一个函数来修改一个DOM元素的几个样式,一般实现:逐个添加样式到DOM元素上;但问题是每修改一个样式,就会引起一次重绘。

function addStyle(element) {  
  element.style.fontWeight = bold;  
  element.style.textDecoration = none;  
  element.style.color = #000;  
}

解决:创建一个class类名,将要修改的样式放在这个类名里,在需要的时候用JS给DOM元素添加这个类名;可以实现添加多个样式但只触发一次重排(改变元素位置或大小)或重绘(只改变样式不改变位置大小)

.addStyle {  
  font-weight: bold;  
  text-decoration: none;  
  color: #000;  
}  
function addStyle(element) {  
  element.className = addStyle;  
}

2、在非渲染区修改DOM元素样式

上一个方法是修改一个DOM元素的样式,如果用相同的样式修改多个DOM元素,可以使用这个方法

需求: 写一个函数修改一个指定元素的子元素中所有超链接的样式名。实现:遍历每个超链接修改他们的样式名。问题:每修改一个,会导致一次重绘

function updateAllStyle(element, anchorClass) {  
  var anchors = element.getElementsByTagName(a);  
  for (var i = 0, length = anchors.length; i < length; i ++) {  
     anchors.className = anchorClass;       //替换类名
//   anchors.setAttribute("class","类名")   //替换类名
//   anchors.classList.add("类名")          //添加类名
  }  
} 

解决:把被修改的元素从DOM中移除,修改所有样式后,再把这个元素插回到原来的位置。

为了完成这个复杂的操作,我们可以先写一个可重用的函数,它不但移除了这个DOM节点,还返回了一个把元素插回到原来的位置的函数  。

function removeToInsertLater(element) {  
  var parentNode = element.parentNode;  
  var nextSibling = element.nextSibling;  
  parentNode.removeChild(element);  
  return function() {  
    if (nextSibling) {  
       parentNode.insertBefore(element, nextSibling);  
    } else {  
       parentNode.appendChild(element);  
    }  
  };  
}

有了上面这个函数,现在我们就可以在一个不需要解析渲染的元素上面修改那些超链接了  。这样只在移除和插入元素的时候各触发一次重解析  。

function updateAllAnchors(element, anchorClass) {  
  var insertFunction = removeToInsertLater(element);     //返回了一个闭包
  var anchors = element.getElementsByTagName(a);  
  for (var i = 0, length = anchors.length; i < length; i ++) {  
     anchors.className = anchorClass;  
  }  
    insertFunction();                 //这个闭包引用着removeToInsertLater()函数中的变量对象
}

创建插入新的DOM元素

1、插入元素动作放在最后

适合插入一个元素。在创建元素后,先给元素添加所有的样式,最后再把它插入到DOM里面。这个方法使创建一个元素的过程中只引起一次重排(回流)和重绘  。

需求:实现一个函数,在一个指定的父元素上插入一个新的元素(超链接) ,并且添加新元素的样式 。实现:创建元素,插入到DOM里,设置相应的属性  。缺点是插入元素、每添加一次样式属性都会引发重排重绘

unction addElm(parentElement, anchorText, anchorClass) {  
  var element = document.createElement(a);  
  parentElement.appendChild(element);    //先插入元素
  element.innerHTML = anchorText;       //再修改样式
  element.className = anchorClass;     
} 

解决:把插入元素动作放在最后执行,就可以只进行一次重排重绘

var element = document.createElement(a);  
element.innerHTML = anchorText;      //先修改样式
element.className = anchorClass;  
parentElement.appendChild(element);    //最后插入元素到DOM中

2、通过文档片段对象(DocumentFragment)创建一组元素

适合创建并插入多个元素并只触发一次重排重绘。

先在 DOM之外创建一个文档片段对象(不需要解析和渲染),然后我们在文档片段对象中创建很多个元素,最后我们把这个文档片段对象中所有的元素一次性放到DOM里面去,只触发一次重排重绘  。

Vue

  • 什么是MVVM?

  • mvvm和mvc区别?它和其它框架(jquery)的区别是什么?哪些场景适合?

  • 组件之间的传值?

  • Vue 双向绑定原理

  • 描述下 vue 从初始化页面–修改数据–刷新页面 UI 的过程?

  • 虚拟 DOM 实现原理

  • Vue 中 key 值的作用?

  • Vue 的生命周期

  • Vue 组件间通信有哪些方式?

  • vue 中怎么重置 data?

  • 组件中写 name 选项有什么作用?

  • Vue 的 nextTick 的原理是什么?

  • Vuex 有哪几种属性?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值