页面上有个空的无序列表节点,用
表示,通过 JavaScript 动态往列表中插入 3 个
- <ul></ul>
,每个列表项的文本内容是列表项的插入顺序,取值 1, 2, 3;同时绑定 click 事件,单击依次输出 1,2,3。
- <li>
- <ul class="js-container">
- <!-- 动态添加内容 -->
- </ul>
- varcontainerDom = document.querySelector('.js-container'),
- itemDom =null;for(leti =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);
- }
- });
接口表示的是没有父节点的最小的文档对象。它被当做一个轻量版本的
使用,用于存储已排好版的或尚未打理好格式的 XML 片段。可以使用
- Document
方法或者构造函数来创建一个空的 DocumentFragment.
- document.createDocumentFragment
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);
- }
- });
创建动画时,大家经常会想到使用
或
- setTimeout
。使用上述方式有这样几个问题:
- setInterval
或
- setTimeout
仍被执行;
- setInterval
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{varlastTime =0;varvendors = ['ms','moz','webkit','o'];for(varx =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){
- varcurrTime =new Date().getTime();vartimeToCall =Math.max(0,16- (currTime - lastTime));varid = window.setTimeout(function(){callback(currTime + timeToCall);
- }, timeToCall);
- lastTime = currTime + timeToCall;returnid;
- };
- window.cancelAnimationFrame =function(id){clearTimeout(id);
- };
- }
- }
- }());
参考地址: http://creativejs.com/resources/requestanimationframe/ https://www.nczonline.net/blog/2011/05/03/better-javascript-animations-with-requestanimationframe/
来源: http://blog.csdn.net/ligang2585116/article/details/71053133