Open zhaobinglong opened 3 years ago
什么是事件委托:通俗的讲,事件就是onclick,onmouseover,onmouseout,等就是事件,委托呢,就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这个事件。
原理:利用冒泡的原理,把事件加到父级上,触发执行效果。
1.提高性能。 2.新添加的元素还会有之前的事件。 试想一下,一个页面上ul的每一个li标签添加一个事件,我们会不会给每一个标签都添加一个onclick呢。 当页面中存在大量元素都需要绑定同一个事件处理的时候,这种情况可能会影响性能,不仅消耗了内存,还多循环时间。每绑定一个事件都加重了页面或者是运行期间的负担。对于一个富前端的应用,交互重的页面上,过多的绑定会占用过多内存。 一个简单优雅的方式就是事件委托。它是基于事件的工作流:逐层捕获,到达目标,逐层冒泡。既然事件存在冒泡机制,那么我们可以通过给外层绑定事件,来处理所有的子元素出发的事件。
<ul id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
// 一个事件委托的简单实现:
document.getElementById('ulId').onclick = function(e) {
var e = e || window.event;
var target = e.target || e.srcElement; //兼容旧版本IE和现代浏览器
if (target.nodeName.toLowerCase() !== 'ul') {
return;
}
console.log(target.innerHTML);
}
浏览器是单线程运行环境,渲染的时候不能运行js,运行js的时候就不能渲染,所以我们把js耗时操作放入work中,让渲染和业务逻辑分开
// 主线程新建一个work子线程,work.js必须是一个网络文件
var worker = new Worker('work.js');
worker.postMessage('Hello World'); // 主线程给子线程发送消息
worker.postMessage({method: 'echo', args: ['Work']}); // // 主线程调用子线程的方法,同时传参
// 主线程监听子线程发送过来的消息
worker.onmessage = function (event) {
console.log('Received message ' + event.data);
doSomething();
}
// 主线程关闭子线程
worker.terminate();
// 子线程监听主线程发送过来的数据,同时给主线程发送信息
addEventListener('message', function (e) {
postMessage('You said: ' + e.data);
}, false);
js新建节点的时候,每次JavaScript对DOM的操作都会改变当前页面的呈现,并重新刷新整个页面,从而消耗了大量的时间。而createDocumentFragment()的作用,就是可以创建一个文档碎片,把所有的新节点附加其上,然后把文档碎片的内容一次性添加到document中。
// 向页面中添加1000个节点
for (var i = 0; i < 1000; i++)
{
var el = document.createElement('p');
el.innerHTML = i;
document.body.appendChild(el); //直接用appendChild向文档中插入节点
}
var frag = document.createDocumentFragment();
for (var i = 0; i < 1000; i++)
{
var el = document.createElement('p');
el.innerHTML = i;
frag.appendChild(el); //首先将新节点先添加到DocumentFragment 节点
}
document.body.appendChild(frag);//然后用appendChild插入文档中
如果我们一次性渲染刷新几万条数据,页面会卡顿,因此只能分批渲染,既然知道原理我们就可以使用setInterval和setTimeout、requestAnimationFrame来实现定时分批渲染,实现每16 ms 刷新一次
requestAnimationFrame跟setTimeout/setInterval差不多,通过递归调用同一方法来不断更新画面以达到动起来的效果,但它优于setTimeout/setInterval的地方在于它是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销。
可以将它看做一个钩子,刚好卡在浏览器重绘前向我们的操作伸出橄榄枝。实际上它更像定时器,每秒60次执行回调——符合屏幕的刷新频率,遇到耗时长的操作,这个数字会降到30来保证稳定的帧数。语法也很简单:window.requestAnimationFrame(callback)
function refresh(total, onceCount) {
//total -> 渲染数据总数 onceCount -> 一次渲染条数
let count = 0, //初始渲染次数值
loopCount = total / onceCount //渲染次数
function refreshAnimation() {
/*
* 在此处渲染数据
*/
if (count < loopCount) {
count++
requestAnimationFrame(refreshAnimation)
}
}
requestAnimationFrame(refreshAnimation)
}
var io = new IntersectionObserver(callback, option);
// 开始观察
io.observe(document.getElementById('example'));
// 停止观察
io.unobserve(element);
// 关闭观察器
io.disconnect();
http://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html
前端新能优化总纲领:#63
最小化语句数相关
JS代码中的语句数量也会影响所执行的操作的速度。完成多个操作的单个语句要比完成单个操作的多个语句块快。这一条依赖参与人员的自觉性,实施难度大。
用key-value代理循环