Skip to main content

事件委托的性能影响


测试代码#

测试环境为新版 Microsoft EdgeChrome

const inEl = document.createElement('input')inEl.value = 1000document.body.appendChild(inEl)
const btEl = document.createElement('button')btEl.innerText = '刷新'btEl.onclick = () => {  console.warn('------------reload--------------')  createList(Number(inEl.value), onclick)}document.body.appendChild(btEl)
const eventCount = 500
function onclick(el, elIndex) {  console.time(`[独立事件] 操作${eventCount}次当前DOM`)  for (let i = 0; i < eventCount; i++) {    const count = parseInt(elIndex.innerText)    elIndex.innerText = count + 1  }  console.timeEnd(`[独立事件] 操作${eventCount}次当前DOM`)}
function createList(count = 4000, onclick) {  console.time(`[创建] ${count}元素耗时`)  const elUl = document.createElement('ul')
  elUl.addEventListener(    'click',    (e) => {      console.time('事件触发时间差')      /** @type {HTMLElement} */      const countEl = e.target.lastChild
      console.time(`[委托事件] 操作${eventCount}次当前DOM`)      for (let i = 0; i < eventCount; i++) {        e.target.lastChild.innerText = parseInt(countEl.innerText) + 1      }      console.timeEnd(`[委托事件] 操作${eventCount}次当前DOM`)    },    true  )
  for (let i = 0; i < count; i++) {    const elLi = document.createElement('li')    elLi.innerText = 'list-'    const elCount = document.createElement('span')    elCount.innerText = i    const elCount2 = document.createElement('p')    elCount2.innerText = i    elLi.appendChild(elCount)    elLi.appendChild(elCount2)    if (onclick)      elLi.onclick = () => {        console.timeEnd('事件触发时间差')        onclick(elLi, elCount, i)      }    elUl.appendChild(elLi)  }
  document.body.appendChild(elUl)  console.timeEnd(`[创建] ${count}元素耗时`)}

下图是在 Edge 中 1000 个元素渲染测试,快照 1 为使用事件委托,快照 2 为每个元素绑定事件,可以看到是否使用委托在运行速度上几乎没有区别,内存消耗也相差无几。

图 1

下图是 10000 个元素的渲染测试, 运行速度相同,内存消耗有所增加

图 2

下图是 20000 个元素的渲染测试, 运行速度依旧相同,内存消耗显著增加增加

图 3

下图是在 Chrome 中 20000 个元素的渲染测试, 结果与 Edge 中的测试结果保持一致

图 4

结论#

  • 事件委托在运行时性能消耗上无影响
  • 在一些 MVC 框架中涉及到频繁的重渲染时,事件委托具有很大优势
  • 在数据量较大时,使用事件委托可以节约内存占用
  • 对于 Chromium 内核的现代浏览器来说,在数据量小(小于 1000 条)时没有必要使用事件委托
  • 缺点:层级复杂的元素代理繁琐,容易误判