DOM进阶

节点操作

  • 因为节点关系都是只读的,所以 DOM 提供了一些操作节点的方法

创建节点

  • 使用document对象的createElement方法能够根据参数指定的标签名创建一个新的元素。并返回对新元素的引用
  • 使用creatElement方法创建的新元素不会被自动添加到文档里,需要使用appendChild等方法

创建文本节点

  • 使用document对象的createTextNode()方法可创建文本节点
  • 参数是一个字符串
  • 创建的文本节点需要使用appendChild等方法才能插入到元素节点中
  • 当然也可以使用innerHTML方法给元素节点添加内容

插入节点

appendChild()

  • appendChild()方法可以向当前节点的字节点列表的末尾添加新的节点
  • 如果文档树中已经存在参数节点,则将从文档树中删除,然后重新插入新的位置

insertBefore()

  • 使用insertBefore(newChild,oldChild)方法可以在已有的子节点前插入一个新的子节点
  • newChild表示新插入的节点,oldChild用于指定插入节点的后边的相邻位置。
  • 插入成功以后,该方法返回新插入的节点
  • insertBefore可以把指定元素及其所包含的所有子节点都一起插入到指定位置中。同时会先删除移动的元素,再重新插入

复制节点

  • cloneNode()方法可以创建一个节点的副本
  • 参数 true (深复制),复制整个节点和里面的内容zs; false (浅复制),只复制节点不要里面的内容
  • 复制后的新节点,也不会被自动插入到文档,需要用到之前的方法去插入
  • 由于复制的节点会包含原节点的所有特性,如果原节点中包含id属性,就会出现id属性值重叠的情况。为了避免潜在的冲突,应修改其中某个节点的id属性值

删除节点

  • removeChild方法可以从子节点列表中删除某个节点
  • 如果删除成功,则返回被删除的节点,如果失败则返回null
  • 当remove 删除节点的时候,该节点所包含的所有子节点将同时被删除

替换节点

  • replaceChild(new,old)方法可以将某个子节点替换为另一个
  • 替换节点替换的是所有子节点以及包含的所有内容
  • 其中参数new为指定的新节点,old代表被替换的节点
  • 如果替换成功则返回被替换的节点,否则返回null
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>节点的操作</title>
</head>
<body>
<button id="btn1">按钮1</button>
<button id="btn2">按钮2</button>
<button id="btn3">按钮3</button>
<button id="btn4">按钮4</button>
<button id="btn5">按钮5</button>
<button id="empty">清空</button>
<ul id="box">
    <li>11</li>
    <li>22</li>
    <li my = "hello">33</li>
    <li>44</li>
</ul>

<script>
    var oBox = document.getElementById("box");
    var oLis = oBox.getElementsByTagName("li");
    var oBtn1 = document.getElementById("btn1");
    var oBtn2 = document.getElementById("btn2");
    var oBtn3 = document.getElementById("btn3");
    var oBtn4 = document.getElementById("btn4");
    var oBtn5 = document.getElementById("btn5");
    var oEmpty = document.getElementById("empty");
    // 创建一个元素节点
    var newLi = document.createElement("li");
    console.log(newLi);

    //创建文本节点
    var newLiText = document.createTextNode("you 这谁呀 怎么这么帅");
    console.log(newLiText);

    //使用innerHTML给新节点传入内容
    newLi.innerHTML = "今天天气真好 <a herf='###' class='delete'>删除</a>";
    console.log(newLi);

    //给ul的尾部添加一个新的节点
    oBtn1.onclick = function(){
        // oBox.appendChild(newLiText);//插入文本节点
        newLi.appendChild(newLiText);//把文本节点插入新创建的li中
        oBox.appendChild(newLi);//直接插入元素节点

        var oDele = document.getElementsByClassName("delete")[0];
        console.log(oDele);
        oDele.onclick = function () {
            // console.log(oDele.parentNode.parentNode.removeChild(oDele.parentNode));;
            // remove(oDele.parentNode)
        }
    }

    //把已经存在的元素插入到某个元素的最后边
    oBtn2.onclick = function () {
        // oBox.appendChild(oLis[1]);
        console.log(oBox.appendChild(this));;//没有限制,只要获取到这个元素,就可以任意插入
    }

    //使用insertBefore插入节点
    oBtn3.onclick = function () {
        // console.log(oBox.insertBefore(newLi, oLis[1]));
        // console.log(oBox.insertBefore(oLis[3], oLis[1]));
        // prependChild(oBox,newLi)
        // insetAfter(newLi,oLis[1])
        // insetAfter(oLis[0],oLis[1])
        insetAfter(newLi,oLis[3]);
    }
    //克隆节点
    oBtn4.onclick = function () {
        console.log(oLis[2].cloneNode());
        console.log(oLis[2].cloneNode(true));
        console.log(oLis[2].cloneNode(false));
        /*var newClone = oLis[2].cloneNode(true);
        oBox.appendChild(newClone)*/
        oBox.appendChild(oLis[2].cloneNode(true));

    }
    //替换节点
    oBtn5.onclick = function () {
        console.log(oBox.replaceChild(newLi, oLis[2]));
        // console.log(document.documentElement.replaceChild(newLi, document.body));
    }

    oEmpty.onclick = function () {
        empty(oBox);
    }

    //在元素的最前边插入节点方法封装
    function prependChild(paren,ele) {
        if (paren.children.length) {
            paren.insertBefore(ele,paren.firstElementChild)
        }else{
            paren.appendChild(ele);
        }
        return ele;
    }
    //在某个节点的后边插入元素 方法封装
    function insetAfter(newele,oldele) {
        if (oldele.nextElementSibling){
            oldele.parentNode.insertBefore(newele,oldele.nextElementSibling);
        }else{
            oldele.parentNode.appendChild(newele);
        }
        return newele;
    }

    //封装函数,传入元素,将该元素在结构中删除
    function remove(ele) {
        if (ele){
            ele.parentNode.removeChild(ele);
            return ele
        }else{
            return undefined;
        }

    }

    //封装函数 传入参数,清空所有子节点
    function empty(ele) {
        while(ele.firstElementChild){
            ele.removeChild(ele.firstElementChild);
        }
    }

</script>
</body>
</html>

元素内容操作

读取和插入HTML字符串

  • 使用元素的innerHTML属性可以返回调用元素所包含的所有子节点对应的HTML标记的字符串
  • 使用innerHTML属性可以根据传入的HTML字符串创建新的DOM片段
  • 然后这个DOM片段完全替换调用元素原有的所有子节点
  • 设置好innerHTML之后,就可以像访问文档中其他节点一样访问新创建的节点
  • 使用documentElement和createTextNode方法创建长的结构,代码会非常长,而innerHTML会执行的更快
  • 大多数浏览器,不支持执行innerHTML插入的script标签

替换HTML字符串

  • outerHTML和innerHTML的功能相同,但是它会包含元素自身。

读写文本

  • innerText 在指定的元素中插入文本,如果文本中包含HTML字符串,将被编码显示
  • outerText功能和innerText功能相似,但是它能覆盖原有的元素。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>元素内容的读取与写入</title>
</head>
<body>
    <button id="btn">按钮1</button>
    <button id="btn2">按钮2</button>
    <button id="btn3">按钮3</button>
    <ul id="box">
        <li>11</li>
        <li>22</li>
        <li>33</li>
        <li>44</li>
    </ul>
    <script>
        var oBtn = document.getElementById("btn");
        var oBtn2 = document.getElementById("btn2");
        var oBtn3 = document.getElementById("btn3");
        var oBox = document.getElementById("box");
        // 01.读取和插入html字符串--innerHTML
        oBtn.onclick = function () {
            // console.log(oBox.innerHTML);//把html也转成字符串输出

            // oBox.innerHTML = "<li>我是创建的li字符串 看我能不能被解析</li>"//替换原有所有内容

            var str = "<li>我是创建的li字符串 看我能不能被解析</li>";
            // oBox.appendChild(str);//appendChild插入字符串无效

            // oBox.innerHTML = oBox.innerHTML + str;

            oBox.innerHTML = str +oBox.innerHTML;
        }

        // 02.替换HTML字符串
        oBtn2.onclick = function () {
            // oBox.outerHTML = "<li>我是创建的li字符串 看我能不能被解析</li>";//包含box一起被替换了
            console.log(oBox.outerHTML);//包含box一起获取到了
        }

        oBtn3.onclick = function () {
            // oBox.innerText = "<li>我是创建的li字符串 看我能不能被解析</li>";
            // console.log(oBox.innerText);

            // console.log(oBox.outerText);
            oBox.outerText = "<li>我是创建的li字符串 看我能不能被解析</li>";
        }
    </script>
</body>
</html>

textContent

  • textContent 属性设置或者返回指定节点的文本内容

    document.getElementById("myList").textContent;
    document.getElementById("myList").textContent = "你好";
  • textContent和innerHTML的区别

    • textContent 会获取style= “display:none” 中的文本,而innerText不会

    • innerText不会理会html格式,直接输出不换行的文本 ,textContent会根据标签里面的元素独立一行

    • innerText 对IE的兼容性较好 ,textContent虽然作为标准方法但是只支持IE8+以上的浏览器

    • 兼容性处理

      function setOrGetContent(node,content) {
          if(arguments.length === 1){
              //代表当前是读取操作
              if(node.textContent){
                  //只要能拿到这个dom对象的textContent属性值,代表当前用户是高级浏览器
                  return node.textContent;
              }else {
                  //代表拿不到  那就是低级浏览器
                  return node.innerText;
              }
          }else if(arguments.length === 2){
              //代表写入操作
              if(node.textContent){
                  //代表高级
                  node.textContent = content;
              }else {
                  //代表低级
                  node.innerText = content;
              }
          }
      }

属性节点

创建属性节点

  • 使用document的createAttribute方法可以创建属性节点
  • 使用属性节点的name属性,可以得到属性的名称
  • 使用属性节点的value属性,可以设置和说去属性的值
  • 创建的属性可以通过setAttributeNode来插入到元素中

读取属性值

  • 在传统的DOM中国,常用点语法通过元素直接访问HTML属性,如src、href等
  • 但是还有很多属性没有支持,需要用规范的写法获取
  • 使用getAttribute方法 可以读取指定属性的值
  • 对于class属性,必须使用className属性名,因为class是JavaScript语言的保留字
  • 对于for属性,则必须使用htmlFor属性名
  • 补充,在脚本化css中设置float属性和text属性,要改为cssFloat和cssText(一次设置多个样式)使用

设置属性值

  • 使用元素的setAttribute(name,value)方法可以设置元素的属性值
  • 参数name和value分别代表属性名称和属性值,并且必须是字符串
  • 如果存在相同属性,则值被刷新,如果不存在则创建属性并添加

删除属性

  • 使用元素的removeAttribute()方法可以删除指定的属性
  • 参数是要删除的属性名
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>属性的节点操作</title>
</head>
<body>
    <button id="btn1">按钮</button>
    <button id="btn2">按钮2</button>
    <ul id="box">
        <li>11</li>
        <li>22</li>
        <li>33</li>
        <li>44</li>
    </ul>
    <div id="con">
        <img src="./a.jpg" alt="我没有" your = "html" class="link">
        <a href="###">我是老A</a>
    </div>
    <script>
        var oCon = document.getElementById("con");
        var oBtn1 = document.getElementById("btn1");
        var oBtn2 = document.getElementById("btn2");
        oCons = oCon.children;

        // 1.创建属性节点
        var newAttr = document.createAttribute("my");
        console.log(newAttr.name);//获取属性节点的名
        console.log(newAttr.value);//获取属性节点的值
        newAttr.name = "your";//name属性这样设置无效
        newAttr.value = "js";//属性的值可以通过属性节点的value设置
        console.log(newAttr);

        //2.读取属性
        console.log(oCons[0].src);
        console.log(oCons[0].your);//不支持
        console.log(oCons[0].alt);
        console.log(oCons[1].href);

        console.log(oCons[0].class);

        console.log(oCons[0].getAttribute("your"));
        console.log(oCons[0].getAttribute("class"));


        //3.设置属性
        oBtn1.onclick = function () {
            oCons[0].alt = "我改变了";

            oCons[0].her = "hahah";//对于自定义属性来说,这样的方法是把标签当成了js对象,给对象扩展的属性和方法

            //如果想要给元素设置自定义属性, 就需要使用setAttribute方法

            oCons[1].setAttribute("his","jQuery");

            console.log(newAttr);

            oCons[0].setAttributeNode(newAttr);

        }

        oBtn2.onclick = function () {
            oCons[0].removeAttribute("your");
        }
    </script>
</body>
</html>

自定义属性

  • HTML5允许用户为元素自定义属性,但是要求添加前缀data-。
  • 目的是为元素提供于渲染无关的附加信息,或者语义信息
  • 可以使用dataset设置自定义属性名,不需要携带前缀
  • 添加自定义属性后,可以通过元素的dataset属性访问自定义属性
  • 删除自定义属性 可以使用delete方法
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义属性</title>
</head>
<body>
<button id="btn">按钮</button>
<div id="box">
    <img src="./01.jpg" alt="图片">
    <span data-name="span">我是span</span>
</div>
<script>
    var oBox = document.getElementById("box");
    var oBtn = document.getElementById("btn");
    var oBoxs = oBox.children;

    oBtn.onclick = function () {
        console.log(oBoxs[1].getAttribute("data-name"));

        console.log(oBoxs[1].dataset);//自身是包含当前元素所有 data- 前缀的属性的集合对象
        oBoxs[1].dataset.sex = "不知道";

        delete oBoxs[1].dataset.name;
    }
</script>
</body>
</html>

文档片段节点

  • DocumentFragment是一个虚拟的节点类型,仅仅存在于内存中,没有添加到文档树中,所以看不到渲染效果
  • 使用文档碎片的好处,就是避免浏览器渲染和占用资源
  • 当文档片段设计完善后,再使用js一次性添加到文档树中显示出来,提高效率,减少页面重绘的次数。解决大量添加节点时候的性能问题
  • 使用document.createDocumentFragment()方法创建,使用appendChild等方法插入
<!DOCTYPE html>d
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>插入节点的性能优化</title>
</head>
<body>
<ul id="box">

</ul>
<script>
    var oBox = document.getElementById("box");
    // 这种方法对DOM节点进行了100次的操作,非常耗费内存
    /*for (var i = 0; i < 100; i++) {
        var newLi = document.createElement("li");
        // textContent给元素插入文本
        newLi.textContent = "hello 6666";
        oBox.appendChild(newLi);
    }*/

    // createDocumentFragment创建一个DocumentFragment,它是一个轻量级的文档格式,作用是临时存储节点,等待插入到文档中
    // createDocumentFragment是解决大量添加节点时候的性能问题
    var fragment = document.createDocumentFragment();
    for (var i = 0; i < 100; i++) {
        var newLi = document.createElement("li");
        // textContent给元素插入文本
        newLi.textContent = "hello 6666";
        fragment.appendChild(newLi);
    }
    oBox.appendChild(fragment);
</script>
</body>
</html>

节点互换练习

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>节点互换练习</title>
    <style>
        *{
            margin: 0;
            padding: 0;
            list-style: none;
        }
        #outer{
            width: 700px;
            margin: 50px auto;
            border: 1px solid #000;
            overflow: hidden;
        }
        #con1{
            width: 300px;
            height: 400px;
            float: left;
            background-color: #4c71ff;
        }f
        #con2{
            width: 300px;
            height: 400px;
            float: right;
            background-color: #4c71ff;
        }
        #controls{
            width: 100px;
            height: 400px;
            float: left;
            background-color: #2ba5eb;
            text-align: center;
        }
        #con1 .red,#con2 .red{
            background-color: red;
        }
    </style>
</head>
<body>
    <div id="outer">
        <ul id="con1">
            <li>我是con1的内容1</li>
            <li>我是con1的内容2</li>
            <li>我是con1的内容3</li>
            <li>我是con1的内容4</li>
        </ul>
        <div id="controls">
            <button id="right">>>>>>>></button>
            <button id="left"><<<<<<<</button>
        </div>
        <ul id="con2">
            <li>我是con2的内容1</li>
            <li>我是con2的内容2</li>
            <li>我是con2的内容3</li>
            <li>我是con2的内容4</li>
        </ul>
    </div>
    <script>
        var oCon1 = document.getElementById("con1");
        var oCon2 = document.getElementById("con2");
        var oRight = document.getElementById("right");
        var oLeft = document.getElementById("left");
        var oCon1Lis = oCon1.getElementsByTagName("li");
        var oCon2Lis = oCon2.getElementsByTagName("li");

        // 给所有的oCon1中的li绑定点击事件,点击以后颜色发生变化,并且被选中
        for (var i = 0; i < oCon1Lis.length; i++) {
            oCon1Lis[i].onclick = function () {
                this.className = "red";
                // 我们给选中的元素一个标记(设置自定义属性 change=true)
                this.setAttribute("change","true");
            }
        }

        // 给oRight绑定点击事件 让选中的左边元素向右移动
        oRight.onclick = function () {
            //遍历所有的左边的li  判断哪一个被选中了
            for (var i = 0; i < oCon1Lis.length; i++) {
                // 判断哪一个li拥有change属性
                if (oCon1Lis[i].getAttribute("change")) {
                    //移动过去的元素 需要把颜色 自定义属性全部还原
                    oCon1Lis[i].className = "";
                    oCon1Lis[i].removeAttribute("change");

                    //把当前遍历的li给移动到oCon2中
                    oCon2.appendChild(oCon1Lis[i]);
                    // 因为移动过元素之后,后边的元素下标全部向上提一位,所以i要减1
                    i --;

                }
            }
        }

        // 给所有的oCon2中的li绑定点击事件,点击以后颜色发生变化,并且被选中
        for (var i = 0; i < oCon2Lis.length; i++) {
            oCon2Lis[i].onclick = function () {
                this.className = "red";
                // 我们给选中的元素一个标记(设置自定义属性 change=true)
                this.setAttribute("change","true");
            }
        }

        // 给oLeft绑定点击事件 让选中的右边元素向左移动
        oLeft.onclick = function () {
            //遍历所有的左边的li  判断哪一个被选中了
            for (var i = 0; i < oCon2Lis.length; i++) {
                // 判断哪一个li拥有change属性
                if (oCon2Lis[i].getAttribute("change")) {
                    //移动过去的元素 需要把颜色 自定义属性全部还原
                    oCon2Lis[i].className = "";
                    oCon2Lis[i].removeAttribute("change");

                    //把当前遍历的li给移动到oCon2中
                    oCon1.appendChild(oCon2Lis[i]);
                    // 因为移动过元素之后,后边的元素下标全部向上提一位,所以i要减1
                    i --;

                }
            }
        }
    </script>
</body>
</html>
posted @ 2023-01-12 22:35  z_bky  阅读(35)  评论(0)    收藏  举报