Dom的映射

704 阅读3分钟

Dom的映射机制: 在js中获取到的元素对象或者元素集合,一般都和页面中的HTML结构存在映射关系(一个变另一个也变)

    比如有个<div></div>
    我们获取该元素对象
    var oBox = document.gtElementByTagName('div');
    //oBox是js中的对象
    oBox.style.backgroundColor = 'orange';
    我们仅仅把oBox堆内存的某些属性,但是同时页面中的div的样式也随之改变,
    映射原理:浏览器在渲染页面的时候会给每个元素设置很多内存属性,在我们修改这些属性的时候,浏览器会兼听到这些修改,然后按照最新的修改重新渲染页面的元素,,
    
    假设有两个div  
    我们可以通过(oBox.length-1)改变页面结构,此时oBox的元素只剩1个,但是当我们想删除最后一个,我们可以
    (oBox.length--);
    (delete oBox[0])
     (oBox[0] = null)
     //输出oBox.length(remove删除的是结构,与我们当前的情况不同)
     你会发后(oBox.length =1),所以我们不存在把集合干掉页面也跟着变得操作,

小结: 相对于Dom元素操作:js中堆内存改变,然后页面结构改变; 而对于集合:页面结构改变,而让元素集合跟着变;

    var oBox = document.querySelectAll()
    现在我们设置(oBox.length - 1) 输出oBox,结果 oBox.length=2;这么看通过querySelectAll获取到的元素结合不存在dom映射机制,因为获取到的集合不是标准的nodelist, 而是属于静态集合,这个集合是不受Dom映射管控的,,
    
    for(var i = 0;i<olist.length;i++){
        LISTBOX.appendChild(olist[i])
    }
    由于dom映射机制,我们在js中把某个li对象(和页面中LI标签一一映射)增加内容的末尾,相当于把页面中的映射的标签挪到容器的末尾,所以不是新增,而是位置的改变,
    那当前如果是新创建的对象,然后append到页面,这样是新增

Dom的重绘和回流,,**重点重点 我们操作Dom 或者 修改 Dom 基本上就是触发他的重绘或者回流机制 重绘:当一个元素的样式发生改变的时候(只有那些不修改元素位置的样式),浏览器会把当前的元素重新渲染(Dom性能消耗低) 回流:当一个元素的位置发生改变,浏览器会重新把整个页面的dom结构进行计算,重新计算出所有元素的最新位置,然后在渲染 (Dom性能消耗非常大):例如, 1,新增或者删除元素(只是资源不用重新加载,但是依然需要重新计算) 2,把现有元素的位置改变,(动画的每一帧)

    解决办法
        1,模版字符串,字符串拼接可以适当减少回流
        2,创建一个文档碎片,var frg = document.createDoumentFragment()
        //创建一个文档碎片,我们可以理解为一个历史存储Dom的容器
        for(var i = 0;i<olist.length;i++){
            frg.appendChild(olist[i])
        }
        LISTBOX.appendChild(arg);//只触发一次Dom回流
        frg = null;
在具体实现中,比如我们要增加很多产品,那么首先要分批增加,在每个小批次中用模版字符串或者文档碎片,但是模版字符串比如需要innerHtml += 相当于把之前的拿出来和现在的拼接起来,然后再放进去,性能消耗可能更大;

在js中我们尽量减少真实dom的操作,减少性能损耗,具体实现框架如react,那么react 是如何实现操作虚拟dom的? 周一会更新 react 中 diff的具体实现