由一道面试题,引发的思考(瞎折腾)

191 阅读3分钟

前言

在一次面试中,面试官提到一个问题,如果有无法避免的重绘或者回流,怎样书写代码,能够增强性能呢?其实我觉得这是个伪命题。具体情况应该具体分析,而且方法无非就是将需要回流的模块脱离文档流,使其尺寸变化不会对外界元素造成影响。

结果,面试官其实想要考察的是css书写规范,他告诉我规范的css书写,能够有效的提升重绘或者回流时的性能,也就是这篇文章描述的中心思想(说错勿喷,这篇文章我也没有细看),其实按照我的传统思维模式,我是不太能接受CSDN上面的文章的,是的,没错,我就是有点看不起CSDN,但我依然对他的诚恳解答表示了感谢。但随后,我又产生了疑惑,按照我现在的知识储备,我觉得css中,属性的顺序,对于性能本身来说应该是没有影响的,于是便有了这篇文章,这也是我的第一篇文章,说的不对的地方,希望大家在评论区指出,非常感谢。

我的认知

掘金1.awebp

按照我的认知,HTML被解析器,解析成DOM Tree,CSS被解析器解析成Style Tree,然后DOM Tree和Style Tree结合,生成Render Tree,接下来才是生成布局,绘制等等。

那么,css的属性顺序怎么可能会影响到重绘和回流呢,无论是怎样的顺序,整个css都会被解析一遍呀。其实到这一步,我已经准备就此打住,不在纠结这个问题了,毕竟《深入理解计算机系统》真好看,于是我将疑惑发了沸点,准备等待大神的解答。

等了一段时间之后,发现大神没有发现这个问题,于是我觉得自己瞎折腾,为了反应性能,其实就是通过window.performance.now()分别计算回流之前,以及回流之后的时间,然后对时间长度进行对比。如果不同写法下,时间长度没有明显差别,那么就证明书写规范仅仅是一个规范而已。

例子

代码如下:

<head>
    <style>
        .container {
            width: 600px;
            height: 600px;
            border: 2px solid #cd0000;
            overflow: hidden;
            font-size: 0px;
        }

        .item {
            width: 8px;
            height: 8px;
            display: inline-block;
            border: 1px solid deepskyblue;
            vertical-align: top;
            font-size: 0px;
            line-height: 0px;
            font-family: "微软雅黑";
            z-index: 1;
            color: #cd0000;
            background-color: #ccc;
        }
    </style>
</head>

<body>
    <div class="container"></div>
    <button id="button">测试</button>
    <script>
        let container = document.querySelector(".container");
        let frame = document.createDocumentFragment();
        for (let i = 0; i < 3000; i++) {
            let div = document.createElement("div");
            div.className = "item";
            frame.appendChild(div);
        }
        container.appendChild(frame);
        let button = document.getElementById("button");
        button.addEventListener("click", function() {
            let start = window.performance.now();
            let item = document.querySelector(".item");
            for (let i = 11; i <= 100; i += 0.1) {
            item.style.width = i + "px";
            item.style.height = i + "px";
        }
        let end = window.performance.now();
        console.log(end - start);
        })
    </script>
</body>

代码很简单,创建了一个容器,然后通过循环生成3000个小方块,然后操作左上角的小方块900次,造成900次回流,然后统计一下900次回流的时间。

我在Chrome93浏览器环境下,通过jsbin运行代码,测试时间显示为2.300000011920929;而我将item中的css样式调整到最下面时,测试时间显示为2.2999999970197678。

然后通过调整操作item的次数,反复实验,我觉得我可以基本得到结论,书写规范,应该只是书写规范,有兴趣的小伙伴可以自己拿代码去试一下。

结论

通过这个事情,我得到三个结论:

  1. 网上的帖子需要自己反复验证,很多帖子其实人云亦云(没错,说的就是你,CSDN)。
  2. 面试官对待面试题要严谨。
  3. 有疑惑,要尽量自己尝试解答,因为解答过程本身也很有趣。 以上!