JavaScript DOM

来源:互联网 发布:淘宝手绘照片是真的吗 编辑:程序博客网 时间:2024/05/23 11:15

一.什么是JavaScript DOM:
JavaScript DOM是Document Object Model for html(HTML 文档对象模型)的缩写。
解释下面几个概念:
A.文档:我们的html页面;
B.文档对象:页面中的元素;
C.文档对象模型:为了能够让程序中的JS去操作页面中的元素而定义的标准。把整个文档看成一棵树,数分枝就是节点,每个节点被定义为DOM节点,同时定义了很多方法来操作这些节点,如getElementById和document.body这些来获取节点的方法

二.DOM节点的常用属性:(后面无括号,且要写成 .XXX 的形式
1.childNodes:获取子节点列表集合,相当于用getElementsByTagName获取的节点集合
注意:A.不止元素节点是节点,节点类型共有12种。当获取一个父元素的childNodes时要比元素数量多,因为可能还会默认包含文本节点(一般为回车符)
B.用childNodes时会出现不兼容的情况:在IE下不会包含文本节点,在标准浏览器下会获取到包含文本节点的所有子元素节点

2.children:同样是获取子节点列表集合,和childNodes作用对应,但与之不同的是,children可以解决上述的浏览器兼容性问题,原因是,children获取的子节点只包含元素节点

3.nodeType:获取当前元素的节点类型,值为1代表元素节点,2代表属性节点,3代表文本节点

补充——属性节点:就是元素的属性
A.获取元素属性:元素.attributes,例如:

<body><button id="btn">click</button><script>  alert(document.getElementById('btn').attributes);</script></body>

这里写图片描述

B.获取属性的名称:元素.attributes[0].name,例如:

<body><button id="btn">click</button><script>   alert(document.getElementById('btn').attributes[0].name);</script></body>

这里写图片描述

C.获取属性的值:元素.attributes[0].value,例如:

<body><button id="btn">click</button><script>alert(document.getElementById('btn').attributes[0].value);</script></body>

这里写图片描述

4.firstChild:获取当前元素的第一个子节点:
注:A.获取到的子节点包含文本类型的节点,所以有浏览器兼容性问题。标准浏览器中的有效写法为:firstElementChild
B.因此,解决此问题的兼容写法应该为:

var oFirst = 元素.firstElementChild || 元素.firstChild;if(oFirst){    oFirst.style...//进行节点操作}

注:上述方法虽然已经是兼容性写法,但仍然会在元素没有子节点时出现问题。最好的办法就是父元素.children[0].style...

5.lastchild:获取当前元素的最后一个子节点,存在兼容性问题,解决方法如下:

var oLast = 元素.lastElementChild || 元素.lastChild;if(oLast){    oLast.style...//进行节点操作}

6.nextSibling:获取当前元素的下一个兄弟节点,存在存在兼容性问题,解决方法如下:

var oElemt = 元素.nextElementSibling || 元素.nextSibling;if(oElemt){    oElemt.style...//进行节点操作}

7.previousSibling:获取当前元素的上一个兄弟节点,存在存在兼容性问题,解决方法如下:

var oElemt = 元素.previousElementSibling || 元素.previousSibling;if(oElemt){    oElemt.style...//进行节点操作}

8.parentNode:获取当前元素的父节点。(父节点只有一个,因此没有兼容性问题

9.offsetParent:获取离当前最近的一个有定位属性的父元素节点。
注:存在兼容性问题如下:
如果没有距离当前元素有定位属性的父元素节点时:
A.在标准浏览器下,会默认为body
B.在IE7及以下浏览器中,若当前元素没有定位就是body,有定位就是html

10.offsetLeft/offsetTop:获取当前元素到有定位属性的父元素的距离(偏移值)
注:存在兼容性问题如下:
A.在标准浏览器中,只要有定位属性的父级节点,left和top值就是相对于父级元素的距离;而其中如果有定位父级节点而元素本身无定位,在IE7及以下浏览器中指的是到body的距离;
B.如果没有定位父级元素,标准浏览器中是指到body的距离;而IE8及以下指的是到html的距离,而且他们的默认margin值不同,因此一定要提前清除默认样式

练习1:封装一个获取元素位置为getPosition方法:

<style type="text/css">body{margin:0;}#div1{padding:40px 20px; background:#00F;}#div2{padding:40px 20px; background:#900; position:relative;}#div3{padding:40px 20px; background:#CF3;}</style><body><div id="div1">    <div id="div2">        <div id="div3"></div>    </div></div><script>    var oDiv1=document.getElementById("div1");    var oDiv2=document.getElementById("div2");    var oDiv3=document.getElementById("div3");    function getPosition(obj){        var json={'left':0,'top':0};        while(obj){            json.left+=obj.offsetLeft;            json.top+=obj.offsetTop;            obj=obj.offsetParent;        }        return json;    };    alert(getPosition(oDiv3).top);    alert(getPosition(oDiv3).left);

这里写图片描述

这里写图片描述
11.offsetWidth/offsetHeight:获取的是盒子的宽、高值,无单位,可用于计算
注意:style.width/style.height获取的是元素style属性里的宽高,有单位,无法直接用于计算

三.操作元素属性的方法(方法后一般有括号)
1.获取元素属性值:元素.value和元素['value'](带有变量的必须用[ ]),例如:

<body><img id="img" src="image/section1.jpg" /><script> alert(document.getElementById('img').src);</script></body>

这里写图片描述

2.获取元素的属性值:元素.getAttribute('属性名'),例如:

<body><button id="btn">click</button><script>    alert(document.getElementById('btn').getAttribute('id'));</script></body>

这里写图片描述

3.设置元素的属性值:元素.setAttribute('属性名','属性值'),例如:

<body><button id="btn">click</button><script>   document.getElementById('btn').setAttribute('style','background:red');</script></body>

这里写图片描述

4.删除元素属性值:元素.removeAttribute('属性名'),例如:

<body><button id="btn">click</button><script>document.getElementById('btn').setAttribute('style','background:red');document.getElementById('btn').removeAttribute('style');</script></body>

这里写图片描述

对此模块的补充:
A.对于自定义属性的获取:用.[]的方法可以在IE8及以下浏览器中取到自定义属性,但是在标准的浏览器下无法取到;用getAttribute()可以在所有浏览器中取到自定义属性。
B.用.src['src']的方法取到的是绝对路径,用getAttribute('src')可以获取到相对路径(但IE7及以下不兼容,仍然是绝对路径)

四.元素的动态创建:
1.动态创建元素的优点:解决了innerHTML累加次数过多造成性能降低的问题;
2.创建元素,举例说明:

var oLi = document.createElement('li');

给创建的元素添加内容:

oLi.innerHTML = ...

3.在父级所有子元素中最后节点后添加元素:父级元素.appendChild(oLi)

4.在父级所有子元素中b节点前添加元素:父级元素.insertBefore(oLi,b)

5.在父级所有子元素中第一个节点前添加元素:父级.insertBefore(oLi,oUl,children[0])
注:存在兼容性问题,在IE中如果没有子元素就会报错,解决方法如下:

oUl.children[0]? oUl.insertBefore(oLi,oUl,children[0]):oUl.appendChild(oLi);

6.删除元素:父级元素.removeChild(oLi)
7.替换子节点:父级元素.replaceChild(新节点,被替换节点)
注:appendChild、insertBefore、replaceChild都是既可以操作动态创建的元素,也可以操作以有的元素,并且是剪切操作

练习2:做一个点击生成留言,要求最多只有5条留言,如果超出会将最早的留言删除

<style type="text/css">ul li{list-style:none;}#text1{width:500px; height:400px; border:1px #999 solid; float:left;}#btn1{cursor:pointer; float:left;}#ul1{width:500px; height:400px; border:1px #999 solid; float:left;}</style></head><body>    <input type="text" id="text1" />    <button id="btn1">生成对话</button>    <ul id="ul1"></ul>    <script>        var oText=document.getElementById("text1");        var oBtn=document.getElementById("btn1");        var oUl=document.getElementById("ul1");        var aLi=document.getElementsByTagName("li");        var num=0;        oBtn.onclick=function(){            var oLi=document.createElement("li");            oLi.innerHTML = oText.value;            oUl.appendChild(oLi);            num++;            if(num>5){                oUl.removeChild(aLi[0]);                num--;            }        }    </script></body>

效果如下:
这里写图片描述

这里写图片描述

练习3:将作业1里面的留言添加一个按钮-批量删除,要求留言有一个点击后背景变成黄色的效果(可以再次点击取消),然后点击批量删除时,删除所有背景颜色为黄色的留言

<style type="text/css">ul li{list-style:none;}#text1{width:500px; height:400px; border:1px #999 solid; float:left;}#btn1{cursor:pointer; float:left;}#ul1{width:500px; height:400px; border:1px #999 solid; float:left;}.col_yellow{background:yellow;}</style></head><body>    <input type="text" id="text1" />    <button id="btn1">生成对话</button>    <button id="btn2">批量删除</button>    <ul id="ul1"></ul>    <script>        var oText=document.getElementById("text1");        var oBtn1=document.getElementById("btn1");        var oBtn2=document.getElementById("btn2");        var oUl=document.getElementById("ul1");        var aLi=document.getElementsByTagName("li");        oBtn1.onclick=function(){            var oLi=document.createElement("li");            oLi.innerHTML = oText.value;            oUl.appendChild(oLi);            for(var i=0;i<aLi.length;i++){                aLi[i].judge=true;                aLi[i].onclick=function(){                    if(this.judge){                                                this.style.backgroundColor='yellow';                        this.judge=false;                    }else{                    this.style.backgroundColor='white';                        this.judge=true;                    }                }            }        }        oBtn2.onclick=function(){            for(var i=0;i<aLi.length;i++){            if(aLi[i].style.backgroundColor=='yellow'){//颜色其实不能用来做判断,在某些情况下可能会出错                    oUl.removeChild(aLi[i]);                    i--;//如果不i--,导致相邻两个留言之间只能删除一个                }                }            }        }    </script></body>

效果如下:
这里写图片描述

这里写图片描述

这里写图片描述

四.HTML DOM className 属性
1.写一个函数funciton getElementsByClassName(),实现返回值为所传参数class类名的元素集合(该方法只能在标准浏览器中使用,ie浏览器中出错)

<body><div class="box box"></div><div class="box1"></div><div class="box box1"></div><ul id="ul1">    <li class="box"></li>    <li class="box"></li>    <li class="box1"></li>    <p class="box"></p></ul><ul id="ul2">    <li class="box"></li>    <li class="box1"></li>    <li class="box1"></li></ul><script>var oUl = document.getElementById('ul1');function ByClass(parent,tagName,className){    var aEls = parent.getElementsByTagName(tagName);    var arr = [];    for(var i=0;i<aEls.length;i++){        var aClassName = aEls[i].className.split(' ');//避免当一个class中包含多个class不被选中的问题        for(var j=0;j<aClassName.length;j++){            if(aClassName[j] == className){                arr.push(aEls[i]);                break;//避免<div class="box box"></div>此种情况重复选择的问题            }        }    }    return arr;}alert(ByClass(oUl,'li','box').length);

2.为元素添加class:
A.首先要明确javascript没有直接给某元素添加类的addClass方法,若需要给某个元素添加类属性时,需采用元素.className +='class名',例如:

<style>   .color-red{background-color: red;}</style></head><body><button id="btn">click</button><script>    document.getElementById('btn').className +='color-red';</script></body>

B.所以要想办法自己封装一个添加类的方法addClass,如下:

function addClass( obj, className){    if( obj.className ==''){        obj.className = className;    }else{        var arrClassName = obj.className.split(' ');        if(arrIndexOf( arrClassName, className) ==-1){            obj.className += ' '+className;        }        //在已有的class名中判断,若没有就添加    }}function arrIndexOf(arr,v){    for(var i=0;i<arr.length;i++){        if(arr[i]==v){            return i;        }    }    return -1;}

3.删除元素的class:
A.同样,javascript没有直接给某元素添加类的addClass方法,若需要给某个元素添加类属性时,需采用元素.className ='',例如:

<style>   .color-red{background-color: red;}</style></head><body><button id="btn">click</button><script>    document.getElementById('btn').className = '';</script></body>

B.那么同样也需要自己封装一个删除class的方法removeClass,但是注意不能直接使用元素.className = '',因为会将所有的class都清空掉。如下:

function removeClass( obj, className){    if(obj.className !=''){        var arrClassName = obj.className.split(' ');        if(arrIndexOf( arrClassName,className )!=-1 ){            arrClassName.splice(arrIndexOf( arrClassName,className ),1);            obj.className = arrClassName.join(' ');        }    }}function arrIndexOf(arr,v){    for(var i=0;i<arr.length;i++){        if(arr[i]==v){            return i;        }    }    return -1;}

练习4:将练习3的内容改成className操作完成

<style type="text/css">ul li{list-style:none;}#text1{width:500px; height:400px; border:1px #999 solid; float:left;}#btn1{cursor:pointer; float:left;}#ul1{width:500px; height:400px; border:1px #999 solid; float:left;}.col_yellow{background:yellow;}</style></head><body>    <input type="text" id="text1" />    <button id="btn1">生成对话</button>    <button id="btn2">批量删除</button>    <ul id="ul1"></ul>    <script>        var oText=document.getElementById("text1");        var oBtn1=document.getElementById("btn1");        var oBtn2=document.getElementById("btn2");        var oUl=document.getElementById("ul1");        var aLi=document.getElementsByTagName("li");        oBtn1.onclick=function(){            var oLi=document.createElement("li");            oLi.innerHTML = oText.value;            oUl.appendChild(oLi);            for(var i=0;i<aLi.length;i++){                aLi[i].judge=true;                aLi[i].onclick=function(){                    if(this.judge){                        this.className='col_yellow';                        this.judge=false;                    }else{                        this.className='';                        this.judge=true;                    }                }            }        }        oBtn2.onclick=function(){            for(var i=0;i<aLi.length;i++){                if(aLi[i].className=='col_yellow'){                    oUl.removeChild(aLi[i]);                    i--;                }            }        }    </script></body>

五.表格的DOM操作
1.浏览器在解析table的时候,会自动加一个tbody(表格正文), 这样直接通过表格元素.childred[1]去获取tr的时候会出错,因此html里table最好直接加上thead和tbody
2.由于用children去一级一级获取元素比较麻烦,JS提供了一些方法:tHead/tBodies/tFoot/rows/cells(表格头/表格正文/表格尾/行/列),例如,oTab.tBodies[0].rows[1].cells[1]就可以获取到表格第一个正文中第二行第二列表格中元素

例如:

<table width="100%" id="table1" border="1" bordercolor="#000">    <thead>        <tr>            <th>1</th>            <th>1</th>            <th>1</th>            <th>1</th>        </tr>    </thead>    <tbody>        <tr>            <td>2</td>            <td>2</td>            <td>2</td>            <td>2</td>        </tr>        <tr>            <td>3</td>            <td>3</td>            <td>3</td>            <td>3</td>        </tr>        <tr>            <td>4</td>            <td>4</td>            <td>4</td>            <td>4</td>        </tr>    </tbody></table><script>var oTab = document.getElementById('table1');oTab.tBodies[0].rows[1].cells[1].style.backgroundColor = 'red';</script></body>

这里写图片描述

注:一个表格里只能有一个表格头和尾,其他可以多个

练习5:用动创建元素的方法生成一个九九乘法表

<style>table{border-bottom:1px #999 solid; border-left:1px #999 solid; border-collapse:collapse;}td{border-right:1px #999 solid; border-top:1px #999 solid; padding:10px; text-align:center;}</style></head><body><!--<table id="table1"></table>--><script>    //获取body标签    var oBody = document.getElementsByTagName("body")[0];    //创建一个<table>元素和一个<tbody>元素    var oTable=document.createElement('table');    var oTableBody = document.createElement("tbody");    for(var i=0;i<9;i++){        var row=document.createElement("tr");        for(j=0;j<=i;j++){        var col=document.createElement("td");        //创建一个文本节点        var oText = document.createTextNode((j+1)+'*'+(i+1)+'='+(j+1)*(i+1));        col.appendChild(oText);        row.appendChild(col);    }        oTableBody.appendChild(row);        oTable.appendChild(oTableBody);        oBody.appendChild(oTable);    }</script></body>

效果如下:
这里写图片描述

练习6:var data = [{},{},{},{}]; //写四个数据,里面包含id,username,sex和操作,并把它们动态添加到table里
要求:用DOM操作,隔行变色(白色灰色),操作为删除一行(删除后仍然隔行变色)

<style type="text/css">table{border:1px #000 solid; border-collapse:collapse;}tr{text-align:center;}td{width:150px; height:100px; border:1px #000 solid;}.background_white{background:#fff;}.background_gray{background:#ccc;}</style></head><body>    <script>        var data = [{'id':1,'username':'小一','sex':'男'},{'id':2,'username':'小二','sex':'女'},{'id':3,'username':'小三','sex':'男'},{'id':4,'username':'小四','sex':'女'}];        var num=0;        var oTable=document.createElement("table");        var oTbody=document.createElement("tbody");        var aA=oTbody.getElementsByTagName("a");        var aTr=oTbody.getElementsByTagName("tr");        for(var i=0;i<data.length;i++){            var oTr=document.createElement("tr");            num++;            if(num%2){                oTr.className='background_white';            }else{                oTr.className='background_gray';            }            var dataJson=data[i];            for(var attr in dataJson){                var oTd=document.createElement("td");                oTd.innerHTML=dataJson[attr];                oTr.appendChild(oTd);            }            var oTd=document.createElement("td");            oTd.innerHTML+='<a href="javascript:;">删除</a>';            oTr.appendChild(oTd);            oTbody.appendChild(oTr);                for(var j=0;j<aA.length;j++){                aA[j].onclick=function(){                    oTbody.removeChild(this.parentNode.parentNode);                    num--;                    for(var k=0;k<num;k++){                        if(k%2){                            aTr[k].className='background_gray';                        }else{                            aTr[k].className='background_white';                        }                    }                }            }        }        oTable.appendChild(oTbody);        document.body.appendChild(oTable);    </script></body>

效果如下:
这里写图片描述

这里写图片描述

六.表单的DOM操作:

1.form里的元素中有个比id更重要的属性–name,而js也可以通过 oForm.name值,就可以获取到这个元素,并且兼容所有浏览器

2.如果是单选和多选(name值相同为一组)时,用oForm.name值的方法获取的是一组元素,就不能直接控制了,可以循环来加事件

3.onchange事件:当表单里的值发生变化时触发(表现为失去焦点时触发,但是如果值不变就不会触发),例如:

<body><input type="text" id="text" /><script>    var oText = document.getElementById('text');    oText.onchange = function(){        alert("我的内容改变了!");    }</script></body>

效果如下:
往文本框里输入内容(表单获取焦点):
这里写图片描述
输完之后在空白处点击一下(文本框失去焦点,onchange事件被触发):
这里写图片描述

注:type = radio标准浏览器点击时只要值变了就会触发,非标准(ie8及以下)下离开时才会触发

4.接下来的内容用下面这个例子说明表单的常用操作:

<select name='city'>    <option value=''>请选择城市</option>    <option value='北京'>北京</option>    <option value='上海'>上海</option></select>

A.获取表单的值就是选择项的value值;
B.单选框、多选框和下拉框的选中状态:

元素.checked = true  //被选中状态元素.checked = false  //未被选中状态

练习7:对上述表单操作的练习:

<body><form id="form1" action="https://www.baidu.com/">    <input type="text" name="inp"/>    <input type="button" name="click1" value="按钮"/>    <input type="radio" name="sex"/><input type="radio" name="sex" /><select name='city'>        <option value=''>请选择城市</option>        <option value='北京'>北京</option>        <option value='上海'>上海</option>    </select>    <input type="submit" value="提交"/>    <input type="reset" value="重置"/></form><script>var oForm = document.getElementById('form1');oForm.sex[0].checked = true;alert(oForm.sex.length);oForm.inp.onchange = function(){    alert(1234);}oForm.click1.onclick = function(){    alert(oForm.city.value);}oForm.onsubmit = function(){    if(oForm.inp.value==''||oForm.inp.value==' '){        alert('请输入内容');        return false;    }}setTimeout(function(){    oForm.submit();},5000)oForm.onreset = function(){    if(!confirm('是否重置')){        return false;    }}</script></body>

5.表单的事件和方法:
A.onsubmit事件:当表单提交时,(点击submit时)
B.submit方法:表单元素.submit(),一般用于页面刷新时自动提交或自动延时提交表单等。
C.reset事件:当表单重置的时候(点击reset时)

练习8:点击重置时让其确定,是否重置(用confirm()返回值,点击确定返回true,反之)

<body>    <form id="form1" action="http://www.baidu.com">        <input type="text" name="text1" />        <input type="submit" value="提交" name="inp" />        <input type="reset" value="重置" />    </form>    <script>        var oForm=document.getElementById("form1");         oForm.onsubmit=function(){            if(oForm.text1.value==''){                alert("请输入内容!");                return false;            }else{                oForm.submit();            }        }        oForm.onreset =function(){            if(!confirm("确定重置吗?")){                return false;            }            //用confirm来判断对浏览器弹框作出的选择,点击确定返回true,点击取消返回false        }    </script></body>
0 0