Javascript操作DOM的API详解及使用小技巧相关笔记(一)

1.DOM是由节点组成的,操作DOM实际上就是操作节点,DOM是html文档的模型抽象,数据是以树的形式在内存中排列的。

2.获取节点或者访问节点的方式有两种,一是直接获取,二是通过访问关系来间接获取,也就是根据自己来找与自己有关系的节点如自己的兄弟节点、父亲节点、儿子节点等等,节点的访问关系是以属性形式存在的。
◆找自己上一个兄弟节点
◇当前节点.previousElementSibling,这个找的是元素节点,但是在IE678中返回值是undefined,所以只能在非IE678中使用
◇当前节点.previousSibling,这个找的是节点,也就是文本节点属性节点注释节点都包含在内,所以不是很好用,但是在IE678中可以使用
◆找自己下一个兄弟节点
◇当前节点.nextElementSibling,这个找的是元素节点,但是在IE678中返回值是undefined,所以只能在非IE678中使用
◇当前节点.nextSibling,这个找的是节点,也就是文本节点属性节点注释节点都包含在内,所以不是很好用,但是在IE678中可以使用
◆找自己的父节点
◇当前节点.parentNode,这个找的是元素节点,自己的父元素节点
◆找自己的父节点中的第一个子节点
◇当前节点.parentNode.firstElementChild,这个找的是元素节点,但是在IE678中返回值是undefined,所以只能在非IE678中使用
◇当前节点.parentNode.firstChild,这个找的是节点,也就是文本节点属性节点注释节点都包含在内,所以不是很好用,但是在IE678中可以使用
◆找自己的父节点中的最后一个子节点
◇当前节点.parentNode.lastElementChild,这个找的是元素节点,但是在IE678中返回值是undefined,所以只能在非IE678中使用
◇当前节点.parentNode.lastChild,这个找的是节点,也就是文本节点属性节点注释节点都包含在内,所以不是很好用,但是在IE678中可以使用
◆找自己的父节点中所有的子节点
◇当前节点.parentNode.childNodes,通过自己间接找到父节点下的所有子节点 包括 文本节点等等 返回值是一个数组 (是w3c标准),但是不是很好用,因为需要判断是否是元素节点。
◇当前节点.parentNode.children,通过自己间接找到父节点下的所有子元素节点  返回值是一个数组 (非w3c标准,但是由于好用,所有浏览器都支持)

★怎么样判断一个节点是否是元素节点,nodeType==1就是元素节点,nodeType==2就是属性节点,nodeType==3就是文本节点

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>直接与间接获取节点</title>
</head>
<body>
<div class="box1">

    <div class="box2" id="box2" name="box2">  </div>

    <div class="box3">  </div>

</div>
<script>
    //直接获取节点 通过id
    var box2 = document.getElementById("box2");
    //直接获取节点 通过class
//    var box2 = document.getElementsByClassName("box2")[0];
    //直接获取节点 通过标签名
//    var box2 = document.getElementsByTagName("div")[1];
    //直接获取节点 通过name
//    var box2 = document.getElementsByName("box2")[0];

    console.log(box2);//输出自己当前节点

    console.log(box2.parentNode);//通过自己间接找到父节点

    console.log(box2.nextElementSibling||box2.nextSibling);//通过自己间接找到下一个兄弟节点

    console.log(box2.nextElementSibling.previousElementSibling||box2.nextSibling.previousSibling);//通过自己间接找到下一个兄弟节点的上一个兄弟节点

    console.log(box2.parentNode.firstElementChild||box2.parentNode.firstChild);//通过自己间接找到父节点下的第一个子节点

    console.log(box2.parentNode.lastElementChild||box2.parentNode.lastChild);//通过自己间接找到父节点下的最后一个子节点

    console.log(box2.parentNode.childNodes);//通过自己间接找到父节点下的所有子节点 包括 文本节点等等 返回值是一个数组
    console.log(box2.parentNode.children);//通过自己间接找到父节点下的所有子元素节点  返回值是一个数组

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


3.节点操作分为三种
◆节点的创建
◇使用 var 节点名=document.createElement("div"); 创建一个新的元素节点,方法中传标签名,是div就传“div” 是table 就传table
◆节点的添加 
◇父节点.appendChild(节点名) 将某个节点添加到父节点里面的最下面
◇父节点.insertBefore(子节点名,参考节点名);将某个节点添加到父节点里面的 某一个参考节点的上面  如果参考节点为null  那么效果和appendChild一样。
◆节点的删除 
◇父节点.removeChild(子节点) 父节点删除某个子节点
◇当前节点.parentNode.removeChild(当前节点) 自己删除自己
★节点的克隆
◇浅克隆  var 新节点=旧节点.cloneNode();//表示克隆当前旧节点,但是不会克隆旧节点内部的子节点

◇深克隆 var 新节点=旧节点.cloneNode(true);//表示克隆当前旧节点,不仅会旧节点而且还会克隆旧节点内部的子节点

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>操作节点</title>
</head>
<body>
<div class="box1" id="box1">

    <div class="box2" id="box2" name="box2">  </div>

    <div class="box3" id="box3">  </div>

</div>
<script>


    //创建一个div元素节点
    var div=document.createElement("div");
    var li=document.createElement("li");

    //在box1节点里的末尾处插入 新创建的div元素节点
    box1.appendChild(div);

    //在box1节点里面 把li节点插入到div节点之前 如果参考对象为null 那么效果和appendChild一样
    box1.insertBefore(li,div);

    //在box1节点里面 把 li节点删除掉
    box1.removeChild(li);

    div.parentNode.removeChild(div);//自杀 div节点自己删除自己

    //克隆
    var newBox1=box1.cloneNode();//浅复制
    console.log(newBox1);
    var newBox_1=box1.cloneNode(true);//深复制
    console.log(newBox_1);

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


4.节点的属性操作分为三种 (但是在IE67中没有得到支持)
◆getAttribute()//获取属性
◇对象名.getAttribute("class");表示获取类属性值,而对象名.className和对象名["className"]也是获取类属性值,两者不同之处在于,前者只是获取页面标签显示的属性值,并不会真正从对象中去找页面标签转换为对象后的属性,只会去找页面标签本身,页面标签有哪些属性,就只能找到哪些属性值,如果页面标签中没有这个属性就会直接返回一个null,后者只会获取页面标签转换为对象后的属性,转换后的对象的属性非常庞大,如果页面标签没有写,页面标签转换为的对象,该对象中也会有默认值,除非这个页面标签根本就不可能有这个属性,那么就是undefined
◇◇这两者不同的地方是前者获取的属性是存到页面标签里的,后者获取的属性是存在页面标签转换后的对象中
◇◇这两者相同的地方是前者不会去获取后者新增加的页面标签本不可能有的属性值,后者不会去获取前者新增加的页面本不可能有的属性值
◆setAttribute()//设置属性
◇对象名.setAttribute("name","img_1");表示设置元素的name属性,如果页面标签有这个属性值则会进行修改,如果页面标签没有这个属性值则会进行添加,注意点,如果添加的这个属性不是该标签应该有的,那么只能通过对象名.getAttribute()方法来获取,并不能通过 对象.该属性名  和对象["该属性名"]的方式来获取,如果新增什么原始标签本不该有的属性,这两者都是独立访问的,并不会相互影响。
◆removeAttribute()//移除属性
◇对象名.removeAttribute("name");表示移除 名为name 的属性,一定要页面标签上显示的属性才能够移除,仅仅只是移除页面标签上的属性,移除后 通过对象.getAttribute("name");再获取,返回值为null,如果通过对象.name和对象["name"]来获取则会返回默认值空字符串,所以这二者在页面标签本该有的属性上,会互相影响,但是前者针对的页面标签本身,后者针对的是页面标签转换后的对象本身
◇◇猜测是前者针对的页面标签其实后来是转换为了一个匿名对象,页面标签明显的显示了几个属性,那个匿名对象就会有几个属性。

◇◇而后者针对的页面标签转换后的对象是真正的对象,就算页面标签没有明显的显示的属性,在那个对象中也会有,并且那些属性都会被赋以默认值。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>节点的属性操作</title>
    <script>
        window.οnlοad=function(){
            var jd=document.getElementById("jdid");

            console.log(jd);
            //直接通过对象的两种方式来操作节点的属性  节点的属性是可读可写的
            console.log(jd.name);
            console.log(jd["name"]);
            console.log(jd.src);
            console.log(jd["src"]);
            console.log(jd.title);
            jd.title="京东京东叮咚";
            jd.flag="标记";
            jd.id="jddid";
            console.log(jd["title"]);
            console.log(jd.tagName);
            console.log(jd["tagName"]);
            console.log(jd.className);
            console.log(jd["className"]);
            console.log(jd.alt);
            console.log(jd["alt"]);

            //通过对象的方法来操作节点的属性  但是IE67不支持
            console.log(jd);
            //获取属性的方法
            console.log(jd.getAttribute("name"));
            console.log(jd.getAttribute("id"));
            console.log(jd.getAttribute("title"));

            //设置属性的方法  有就修改  没有就添加
            jd.setAttribute("name","叮咚");
            console.log(jd.getAttribute("name"));
            jd.setAttribute("flag","标2222222222222记");

            //删除属性的方法
            jd.removeAttribute("name");
            jd.removeAttribute("name");
            console.log(jd.name);
            console.log(jd["name"]);
            console.log(jd.getAttribute("name"));
            console.log(jd.getAttribute("name"));//null
            jd.setAttribute("name","叮咚");
            console.log(jd.getAttribute("name"));//叮咚

            jd=document.getElementById("jddid");
            console.log(jd);
//            jd.removeAttribute("name");


            //说白了 1.一个是将页面元素转换成了对象,然后对象进行操作 这种方式并不一定能够展现在页面标签上  2.一个是直接操作页面元素的标签 这种操作方式 能够直接体现在页面标签上
        }
    </script>
</head>
<body>
<img src="images/jd1.png" name="jdname" id="jdid" title="京东狗" alt="jd1.png" class="jdclass">
</body>
</html>


5.终止页面的超链接的默认跳转行为,可以使用return false;

◆<a href="www.baidu.com" style="display:block;" οnclick="fn(); return false;" >切换</a> 表示执行一个方法后就return false;,其实行内的方式使用的是第三种函数定义的方式,new Function("fn(); return false;");,所以页面的行内绑定事件其实是 οnclick=new Function("fn(); return false;");,行内绑定事件其实绑定的函数一定得是全局的,如果你绑定的那个函数在另一个函数里面,那么那个函数就是局部的函数,所以就访问不了,自然也调用不了。

◆ a.οnclick=function(){return false;//终止a链接的默认跳转行为};表示 return false;终止 a链接的默认跳转行为,和上面的差不多,但是它使用的是第一种函数定义的方式,匿名方式绑定事件。


6.使用循环绑定事件的时候,由于函数加载时只会加载函数名,所以就会造成函数体内的i不是每一次循环的i,而是最终循环绑定事件完毕后的i,函数只有在调用的时候才会加载函数体,然而函数调用时也是循环绑定事件结束的时候,所以解决这个问题的方法是,在函数里面获取当前元素对象时,不要用 数组对象[i]的方式获取,改用this,this关键字表示,谁调用这个函数,this就会指向谁,这样就不会报错了,当函数开始报错,那么就会终止当前函数执行,当前函数就不会往下执行了,但是只是不会执行这个函数,其它的语句块会照样执行。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>仙女相册</title>
    <style type="text/css">
        body {
            font-family: "Helvetica", "Arial", serif;
            color: #333;
            background-color: #ccc;
            margin: 1em 10%;
        }

        h1 {
            color: #333;
            background-color: transparent;
        }

        a {
            color: #c60;
            background-color: transparent;
            font-weight: bold;
            text-decoration: none;
        }

        ul {
            padding: 0;
        }

        li {
            float: left;
            padding: 1em;
            list-style: none;
        }

        #imagegallery {

            list-style: none;
        }

        #imagegallery li {
            margin: 0px 20px 20px 0px;
            padding: 0px;
            display: inline;
        }

        #imagegallery li a img {
            border: 0;
        }
    </style>

</head>
<body>
<h2>
    美女画廊
</h2>
<a href="#">注册</a>
<ul id="imagegallery">
    <li>
        <a href="images/1.jpg" title="美女A">
            <img src="images/1-small.jpg" width="100" alt="美女1"/>
        </a>
    </li>
    <li>
        <a href="images/2.jpg" title="美女B">
            <img src="images/2-small.jpg" width="100" alt="美女2"/>
        </a>
    </li>
    <li>
        <a href="images/3.jpg" title="美女C">
            <img src="images/3-small.jpg" width="100" alt="美女3"/>
        </a>
    </li>
    <li>
        <a href="images/4.jpg" title="美女D">
            <img src="images/4-small.jpg" width="100" alt="美女4"/>
        </a>
    </li>
</ul>


<div style="clear:both"></div>

<img id="image" src="images/placeholder.png" width="450px"/>

<p id="des">选择一个图片</p>

<script>
    //需求:当点击小图片时在小图片下方显示大图片
    //步骤:
    //1 获取ul元素 根据ul元素找到a标签
    //2 使用循环绑定事件
    //3 书写事件驱动程序

    //1 获取ul元素 根据ul元素找到a标签
    var ul = document.getElementById("imagegallery");
    var aArr = ul.getElementsByTagName("a");
    var img = document.getElementById("image");
    var p = document.getElementById("des");

    //2 使用循环绑定事件
    for (var i = 0; i < aArr.length; i++) {
        aArr[i].οnclick=function(){
            //3 书写事件驱动程序
            img.src=this.href;
            p.innerHTML=this.title;

            //下面这种做法不可行  因为 函数在加载时只会加载函数名,不会加载函数体,只有在调用的时候才会加载函数体,所以当函数调用的时候,for循环绑定事件就已经结束了,那个时候 i的值就是4了,所以你调用的时候根本找不到这个a标签对象,因为没有这个a标签对象,所以就会报错,便不会执行最后面的return false,于是就会去执行a标签默认跳转行为。
//            alert(i);
//            img.src=aArr[i].href;
//            p.innerHTML=aArr[i].title;

            //终止a链接的默认跳转行为  但是只要函数执行到这里来报错 就会直接终止这个函数往下执行 就不会执行下面的 return false;
            return false;
        }
    }

    //3 也可以使用这种方式来循环绑定事件
    for (var i = 0; i < aArr.length; i++) {
        //使用闭包的方式,在某一块儿作用域内定义一个局部变量,内部可以访问外部的,这样每次循环都会出现一个局部变量i在这个函数中。
        aArr[i].οnclick= (function(i){
            return function(){
                //3 书写事件驱动程序
                img.src=aArr[i].href;
                p.innerHTML=aArr[i].title;
                return false;
            }
        })(i);
    }

</script>

</body>
</html>

7.可以通过标签来找标签里面的子标签,如

根据id获取ul元素,然后根据ul元素找到内部的a标签,var ul = document.getElementById("imagegallery");,var aArr = ul.getElementsByTagName("a");


8..innerHTML、innerText、textContent、value属性
◆innerHTML属性是获取双标签元素<x></x>之间的内容,可以识别html标签
◆innerText属性也是获取双标签元素<x></x>之间的内容,不可以识别html标签,只能识别文本,但是在老版本火狐里面不支持innerText属性,只支持textContent属性
◆textContent属性也是获取双标签元素<x></x>之间的内容,不可以识别html标签,可以识别文本,但是在IE678里面不支持textContent属性,只支持innerText属性

◆value属性 是获取 带有value属性的标签的value属性值, 如 <input type='text' value="123" /> 或者<input type='button' value='按钮'/> 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>value与innerHTML等等</title>

</head>
<body>
<input type="text" value="文本标签1" id="txt">
<div id="box1">
    box1
    <div id="box2">
        box2
    </div>
</div>
<div id="box3">
    box3
    <div id="box4">
        box4
    </div>
</div>

<script>
    console.log(txt.value);//获取带有value属性的标签的value属性值
    console.log(box1.innerHTML);//获取双标签闭合之间的内容  可以识别标签
    console.log(box1.innerText);//获取双标签闭合之间内容  不可以识别标签 老版本火狐不支持 innerText 但是支持 textContent
    console.log(box1.textContent);//获取双标签闭合之间内容  不可以识别标签    IE678不支持 textContent 但是支持innerText

</script>

</body>
</html>


9.当页面标签拥用了id属性时,可以省略获取该标签的对象的部分的代码,直接把该标签的id属性值当作一个对象拿来用即可,但是并不推荐这么使用,因为代码的可读性就变差了,但是内部原理是,js引擎首先会去找这么一个变量,如果找不到,它就会去页面中找一个id属性值为为这个变量的标签,之后就会获取这个标签元素对象,最后进行操作。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值