DOM操作
来源:互联网 发布:天龙抢号软件 编辑:程序博客网 时间:2024/06/05 19:33
页面上有个空的无序列表节点,用
<ul></ul>
表示,通过JavaScript动态往列表中插入 3 个<li>
,每个列表项的文本内容是列表项的插入顺序,取值 1, 2, 3;同时绑定click事件,单击依次输出1,2,3。
<ul class="js-container"> <!-- 动态添加内容 --></ul>
动态添加li
var containerDom = document.querySelector('.js-container'), itemDom = null;for(let i = 1; i <= 3; i++) { itemDom = document.createElement("li"); itemDom.innerText = i; containerDom.appendChild(itemDom);}
绑定事件
var containerDom = document.querySelector('.js-container'), itemDom = null;for(let i = 1; i <= 3; i++) { itemDom = document.createElement("li"); itemDom.innerText = i; itemDom[i].addEventListener('click', function() { alert(i); // alert(this.innerText); }); containerDom.appendChild(itemDom);}
需要注意: 上述使用let
局部作用域(使用闭包同样可以实现)!绑定事件使用addEventListener
,而没有使用内联事件onclick
。是因为内联事件是作为元素属性保存起来的,这些属性可以被覆盖,所以如果为同一个事件绑定了多个处理程序,那么最后一个处理程序会覆盖之前的。
增大数据量
如果将li的数量改为500,5000甚至更大呢?页面必然会出现卡顿或者直接卡死。
事件代理,减少事件数量
var containerDom = document.querySelector('.js-container'), itemDom = null;for(let i = 1; i <= 500; i++) { itemDom = document.createElement("li"); itemDom.innerText = i; containerDom.appendChild(itemDom);}// 事件代理containerDom.addEventListener('click', function(e){ const target = e.target; if (target.tagName === 'LI') { alert(target.innerHTML); }});
DocumentFragement可以减少DOM操作
接口表示的是没有父节点的最小的文档对象。它被当做一个轻量版本的 Document
使用,用于存储已排好版的或尚未打理好格式的XML片段。可以使用document.createDocumentFragment
方法或者构造函数来创建一个空的 DocumentFragment.
DocumentFragement通常用来创建一个文档片段,然后将创建的DOM元素插入到文档片段中,最后把文档片段插入到DOM树中。在DOM树中,文档片段会被替换为它所有的子元素。因为文档片段存在于内存中,并不在DOM树中,所以将子元素插入到文档片段时不会引起页面重绘(reflow)(对元素位置和几何上的计算)。因此,使用文档片段DocumentFragement
通常会起到优化性能的作用。
var containerDom = document.querySelector('.js-container'), contentFragment = document.createDocumentFragment(), itemDom = null;// 先将li添加到contentFragment,已减少dom操作for(let i = 1; i <= 500; i++) { itemDom = document.createElement("li"); itemDom.innerText = i; contentFragment.appendChild(itemDom);}containerDom.appendChild(contentFragment);// 事件代理containerDom.addEventListener('click', function(e){ const target = e.target; if (target.tagName === 'LI') { alert(target.innerHTML); }});
分批处理,requestAnimationFrame平滑过渡
创建动画时,大家经常会想到使用setTimeout
或setInterval
。使用上述方式有这样几个问题:
- 动画区域或者页面已被隐藏,
setTimeout
或setInterval
仍被执行; - 大多数计算机显示器以60Hz的速率刷新,这基本上意味着每秒重新绘制60次。为了得到最平滑的动画,需要设置最佳间隔是1000ms / 60或约17ms,但这不能覆盖全部浏览器;
- 延迟毫秒数并不意味着该毫秒后被执行,仅表示其进行排队。如果UI线程很忙,可能会处理用户操作,那么该代码将不会立即执行;
window.requestAnimationFrame(callback) 方法告诉浏览器您希望执行动画,并请求浏览器调用指定的函数在下一次重绘之前更新动画。该方法将在重绘之前调用的回调作为参数。window.cancelAnimationFrame()
来取消这个回调函数。
const containerDom = document.querySelector('.js-container');const total = 5000, // 5000个li batchSize = 50, // 每一个批次执行50个 batchCount = Math.ceil(total / batchSize); // 批次数let batchDone = 0; // 已经完成的批处理个数/** * 批次插入li */function appendItems() { let contentFragment = document.createDocumentFragment(), itemDom = null; for(let i = 1; i <= batchSize; i++) { itemDom = document.createElement("li"); itemDom.innerText = (batchDone * batchSize) + i; contentFragment.appendChild(itemDom); } containerDom.appendChild(contentFragment); batchDone++; // 调用下一批次 doBatchAppend();}/** * 平滑插入各个批次 */function doBatchAppend() { if (batchDone < batchCount) { // 无需设置时间 window.requestAnimationFrame(appendItems); }}doBatchAppend();// 绑定事件containerDom.addEventListener('click', function(e){ const target = e.target; if (target.tagName === 'LI') { alert(target.innerHTML); }});
注意: requestAnimationFrame()
存在一定的兼容性问题
(function() { if (window.requestAnimationFrame) { return; } else { var lastTime = 0; var vendors = ['ms', 'moz', 'webkit', 'o']; for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; } // 使用setTimeout模拟实现 if (!window.requestAnimationFrame){ window.requestAnimationFrame = function(callback, element) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; window.cancelAnimationFrame = function(id) { clearTimeout(id); }; } }}());
参考地址:
http://creativejs.com/resources/requestanimationframe/
https://www.nczonline.net/blog/2011/05/03/better-javascript-animations-with-requestanimationframe/
- [DOM]javascript DOM操作
- DOM操作
- DOM操作
- DOM操作
- dom操作
- Dom 操作
- Dom操作
- DOM操作
- DOM操作
- #DOM操作
- DOM操作
- DOM操作
- DOM操作
- DOM操作
- DOM操作
- DOM操作
- DOM操作
- DOM操作
- Linux开发--守护进程的创建
- Eclipse注释模板设置详解
- linux shell(二)
- 内核栈空间和用户栈空间
- 给定两个32位的整数n和m,将m插进n的j到i的位置,n其他位置不变
- DOM操作
- SpringMVC HandlerMethodArgumentResolver自定义参数转换器 针对HashMap失效的问题
- Java常用工具类封装——DES加密和解密的工具类
- mysql慢查询
- 中国剩余定理(互质与不互质的情况)
- linux shell (三)
- 【Leetcode 3】Longest Substring Without Repeating Characters
- Java
- C++Primer 5th_Exercise 习题答案