原理篇:js为什么会阻碍浏览器的渲染

一、事件循环

 先说原理,浏览器渲染主进程中只有一个渲染主线程,这个主线程即js的单线程。主线程承担着诸多的工作,渲染页面、执行JS都在其中运行。事件循环又叫做消息循环,是浏览器渲染主线程的工作方式。浏览器的任务存在消息队列当中,每次主线程从消息队列中取出第一个任务执行,执行完毕后再去消息队列中取任务…而在执行当前任务时,可能会产生新的任务,这些新的任务会被添加到消息队列中等待执行。比如计时器时间到了,用户触发了监听事件,浏览器触发了重新渲染,这些任务不会被立马执行,而是等到主线程把当前任务完成才会去执行,这就导致了js阻碍浏览器的渲染,下面看一个例子。

二、举例

<body>
    <button onclick="changeText(this)">改变文字</button>
</body>
<script>
    function sleep(time) {      //辅助函数,阻塞主线程
        let start = Date.now();
        while (Date.now() - start < time) { }
    }
    function changeText(that) {
        that.innerText = '文字已改变';
        console.log(that.innerText);
        sleep(3000);
    }
</script>

 在这个例子中,为按钮绑定了单击事件,触发的时候改变按钮的文字,并且打印改变后的文字内容,再阻塞主线程3秒钟。一般来说,当dom的innerText属性被改变时,浏览器也会即刻展现,这样来说,阻塞3秒的函数写在这里就没什么用了。但事实并非如此,下面看执行结果。
请添加图片描述

三、分析结果

 可以看到,当点击按钮后,控制台立即打印了按钮的innerText,而3秒过后,浏览器才进行渲染。这是因为主线程将js作为全局任务来执行,当改变按钮的innerText属性时,产生了额外的渲染任务,此任务不会被立刻执行,而是被添加到消息队列中,等待主线程将它取出执行。虽然立刻改变了按钮的innerText属性值,但是此时js代码全局任务并没有执行完,还需要执行阻塞3秒的sleep函数。当执行完js所有代码后,主线程才回去消息队列中取出渲染任务,将其渲染到浏览器中。所以总结一句话,js会阻碍浏览器的渲染。

  • 19
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值