javascript中DOM总结(二)

javascript中DOM总结(二)

使用Nodelist
NodeList,和HTMLColletion,以及NamedNodeMap是实时的。所以下面的循环是无限循环

let div = document.getElementsByTagName("div");
    for(let i =0;i<div.length;i++){
      let ele = document.createElement("div");
      ele.appendChild(document.createTextNode("11"));
      document.body.appendChild(ele);
    }
    // 解决方案一:先将长度保存起来
    let div = document.getElementsByTagName('div');
    for(let i =0,len = div.length;i<len;i++){
      let ele = document.createElement("div");
      ele.appendChild(document.createTextNode('11'));
      document.body.appendChild(ele);
    }
    // 解决方案二:使用反向迭代
    let div = document.getElementsByTagName("div");
    for(let i = div.length -1;i>=0;i--){
      let ele = document.createElement("div");
      ele.appendChild(document.createTextNode('11'));
      document.body.appendChild(ele);
    }

一、动态加载脚本文件
①外部引入脚本封装函数

function loadScript(url){
      let script = document.createElement("script");
      script.src = url;
      document.body.appendChild(script);
    }
    loadScript('file.js')

②内部生成标签封装函数(在这里需要考虑ie,对ie浏览器需要设置text),需要使用try–catch来进行设置

function loadScriptString(code){
      var script = document.createElement("script");
      script.type = "text/javascript";
      try{
        script.appendChild(document.createTextNode(code));
      }catch(ex){
        script.text = code;
      }
      document.body.appendChild(script);
    }
    var code = "console.log('大家好aa');"
    loadScriptString(code);

二、动态加载样式
①动态样式,使用外联进行添加

//这里是link标签
    function loadStyle(url){
      var link = document.createElement("link");
      var head = document.getElementsByTagName("head")[0];
      link.rel = "stylesheet";
      link.href = url
      head.appendChild(link);
    }
    loadStyle('file.css');

②动态添加样式,使用内部添加,此时需要注意ie的问题,使用try-catch进行兼容浏览器

//这里是使用style标签
 function loadStyleSheet(code){
      var style = document.createElement("style");
      var head = document.getElementsByTagName("head")[0];
      style.type = "text/css";
      try{
        style.appendChild(document.createTextNode(code));
      }catch(ex){
        style.styleSheet.cssText = code;
      }
      head.appendChild(style);
    }
    var code = "body{background:red}"
    loadStyleSheet(code);  

三、动态操作表格

   let table = document.createElement("table");
    table.border =1 ;
    table.width = "100%";
    // 创建表体
    let tbody = document.createElement("tbody");
    table.appendChild(tbody);
    // 创建第一行
    tbody.insertRow(0);
    tbody.rows[0].insertCell(0);
    tbody.rows[0].cells[0].appendChild(document.createTextNode("11"));
    tbody.rows[0].insertCell(1);
    tbody.rows[0].cells[1].appendChild(document.createTextNode('12'));

    // 创建第二行
    tbody.insertRow(1);
    tbody.rows[1].insertCell(0);
    tbody.rows[1].cells[0].appendChild(document.createTextNode("21"));
    tbody.rows[1].insertCell(1);
    tbody.rows[1].cells[1].appendChild(document.createTextNode('22'));
    
    document.body.appendChild(table);
    // 这样就相比于普通的更简便

如果使用document.createElement创建表格以及代码过于繁琐。
四、MutationObserver对象
MutationObserver对象是可以对一个对象节点进行观察,当其内部的一些属性或者方法发生变化的时候,就会触发,所以其是一个异步函数。
①observe() 传入两个参数,一个是需要监控的对象,另一个是一个键值对,表示需要监控的内容。

    let observer = new MutationObserver(()=>{
      console.log("DOM was mutated");
    })
        observer.observe(document.body,{attributes:true});
    document.body.className = "set";
    console.log("主程序");

这个最终输出结果是:主程序,DOM was mutated,
所以可以看出是异步处理操作。
②MutationRecord对象:其是一个数组,当监控到设置的属性改变时,就会向数组中添加内容。

    let observer = new MutationObserver((MutationRecord)=>{
      console.log(MutationRecord);
    })
    observer.observe(document.body,{attributes:true});
    document.body.setAttribute("foo","bar");

	// 也可以使用setAttributeNs()来设置具有命名的空间属性
    document.body.setAttributeNS("baz","foo",'bar');
//第一个参数就是给attributeNamespace传值。

传给回调的第二个参数,是观察MutationObserver的实例

    let observer = new MutationObserver((MutationRecord,MutationObserver) => {
      console.log(MutationRecord);
      console.log(MutationObserver);
    })
    observer.observe(document.body, { attributes: true });
    document.body.setAttribute("foo", "bar");
    // Array(1)
    // MutationObserver

disconnect()方法:将观察者断开,后面属性改变不会触发异步函数,

    let observer = new MutationObserver((value)=>{
      console.log("Attributes changes");
    })
    observer.observe(document.body,{attributes:true});
    // 这样便会显示Attributes changes
    document.body.className = "foo";
    setTimeout(function(){
      observer.disconnect();
    },0)
    // 这样则不会显示Attributes changes
      document.body.className = "foo";
      observer.disconnect();

MutationObserver()可以同时观察多个对象的属性变化:最终得到的任然是一个数组

      let observer = new MutationObserver((mutationRecords)=>{
        console.log(mutationRecords.map(mutationRecord=>{
          return mutationRecord.target;
        }));
      })
      let div = document.createElement("div");
      let span = document.createElement("span");
      document.body.appendChild(div);
      document.body.appendChild(span);
      observer.observe(div,{attributes:true});
      observer.observe(span,{attributes:true});
      div.setAttribute("foo","bar");
      span.setAttribute("foo","bar");

disconnect()一刀切,将全部的观察去除,没有日志输出

        let observer = new MutationObserver((MutationRecords)=>{
          console.log(MutationRecords.map(MutationRecord=>{
            return MutationRecord.target;
          }));
        })
        let div = document.createElement("div");
        let span = document.createElement("span");
        document.body.appendChild(div);
        document.body.appendChild(span);
        observer.observe(div,{attributes:true});
        observer.observe(span,{attributes:true});
        div.setAttribute("foo",'bar');
        span.setAttribute("bar",'set');
        observer.disconnect();

这里observer.disconnect()是同步的,观察是异步的。
重用MutationServer(),就是先断开,再连上

        let observer = new MutationObserver(MutationRecord=>{
          console.log("Attribute has changed");
        })
        observer.observe(document.body,{attributes:true});
        setTimeout(()=>{
          document.body.className = "foo";
        },0)
        setTimeout(()=>{
          observer.disconnect();
          document.body.className = "bar";
        })
        setTimeout(()=>{
          observer.observe(document.body,{attributes:true});
          document.body.className = "baz";
        },0)

三、MutationObserverInit与观察范围
①观察属性 设置attributes为true

        let observer = new MutationObserver((MutationRecord)=>{
          console.log(MutationRecord);
        })
        let div = document.createElement("div");
        document.body.appendChild(div);
        observer.observe(div,{attributes:true});
        div.setAttribute("foo","bar");
        div.removeAttribute("foo");

②、attributesFilter()设置白名单,是一个数组,并且只会记录这个数组中的属性。

let observer = new MutationObserver((value)=>{
          console.log(value);
        })
        let div = document.createElement("div");
        document.body.appendChild(div);
        observer.observe(div,{attributeFilter:["foo"]});
        div.setAttribute("foo",'bar');
        div.setAttribute("aa",'dssd');

③attributeOldValue属性 使用可以记录这个属性对应的值

        let observer = new MutationObserver((value)=>{
          console.log(value.map(item=>{
            return item.oldValue;
          }));
        })
        let div = document.createElement("div");
        document.body.appendChild(div);
        observer.observe(div,{attributeOldValue:true});
        div.setAttribute("foo","name");
        div.setAttribute("foo","20");
        div.setAttribute("foo","sss");

最终显示结果:[null, “name”, “20”]

观察字符文本
document.body.innerText和document.body.innerHTML两者的区别是innerText是输出body中的文本内容,而innerHTML输出body中的全部内容。
观察子节点
这里创建一个节点和添加一个节点都会被观察到

  document.body.innerHTML = "";
  let observer = new MutationObserver((value)=>{
    console.log(value);
  })
  observer.observe(document.body,{childList:true});
  // 这里创建一个节点和添加一个节点都会被观察到
  document.body.appendChild(document.createElement("div"));

观察子树的变化
这里将参数设置为{attributes:true,subtree:true},就是可以设置该节点以及其子节点的属性的值

    let observer = new MutationObserver((value)=>{
      console.log(value);
    })
    let div = document.createElement("div");
    document.body.appendChild(div);
    observer.observe(document.body,{attributes:true,subtree:true});
    div.setAttribute("foo","bar");

将节点移动到外面吗,任然有效

      document.body.innerHTML = "";
      let observer = new MutationObserver(value=>{
        console.log(value);
      })
      let div = document.createElement("div");
      let span = document.createElement("span");
      div.appendChild(span);
      document.body.appendChild(div);
      observer.observe(document.body,{attributes:true,subtree:true});
      document.body.insertBefore(span,div);
      span.setAttribute("foo","bar");

takeRecords()方法:清空队列,并将观察到的数组返回

      let observer = new MutationObserver((value)=>{
        console.log(value);
      })
      observer.observe(document.body,{attributes:true});
      document.body.className = "foo";
      document.body.className = 'nnn';
      document.body.className = "se";
      console.log(observer.takeRecords());
      console.log(observer.takeRecords());

总结: MutationObserver对象是用来观察某一个对象的属性变化的,当该对象属性发生变化,则会将其放入一个微任务队列中等待执行相关操作。MutationObserver对象对节点对象的引用是弱引用,而节点对象对MutationObserver对象的引用时强引用,当节点消失,MutationObserver会自动触发垃圾回收机制。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值