JS中级课程
(一)DOM元素的具体操作
DOM的概念及节点类型
DOM:全称Document Object Model 文档对象模型
- 文档HTML页面
- 文档对象HTML页面里面的元素
- 文档对象模型: 一套定义,准则为了能够让JS去操作页面中的元素而定义出来的标准
DOM会把文档看做是一棵树,页面中的每一个元素就是树上的节点,同时DOM定义了很多方法,属性来操作这棵树中的每一个元素(节点)---每一个节点称为DOM节点
DOM节点
获取第一级子元素,也就是说孙子节点获取不了
有兼容性问题(空白节点,换行),用了childNodes必须使用nodeType
获取子元素里面的第一个
获取子元素里面的最后一个
1.childNodes
元素.childNodes:只读属性,子节点列表合集
childNodes包含一级子节点,不包含后背孙子及其下面的节点
childNodes的兼容性
- childNodes包含了文本注释元素类型的节点,并且也包含了非法嵌套的节点
- 非标准浏览器下面,包含元素类型的节点,IE7以下不包含非法节点
<ul id="ul1">
<li>111</li>
<li>111</li>
<li>111</li>
<li>111</li>
</ul>
上面是布局,下面是代码
var ul = document.getElementById("ul1");
window.alert(ul.childNodes.length);
//标准浏览器弹出来9;IE67弹出来4因为标准浏览器换行也属于文本节点
for(var i=0;i<ul.childNodes.length;i++)
{
ul.childNodes[i].style["background"] = "red";
//这里标准浏览器下面会报错误,因为有文本节点
}
//解决方案
for(var i=0;i<ul.childNodes.length;i++)
{
if(ul.childNodes[i].nodeType==1)
{
ul.childNodes[i].style["background"] = "red";
}
}
这样就去掉了文本节点
PS:childNodes必须和nodeType一起使用,涉及到空白节点的问题:元素节点的nodeType就是1,属性节点就是2,文本节点nodeType就是3,注释节点就是8,document节点就是9
2.children
元素.children 只读子节点的列表合集。她找的只是元素节点。不包括文本节点,注释节点等等
for(var i=0;i<ul.children.length;i++)
{
ul.children[i].style["background"] = "red";
//这样不会报错误
}
3.nodeType
元素.nodeType:只读,当前元素的节点类型
nodeName:获取的就是节点的名称
4.attributes
元素.attributes:只读属性
属性节点
<div id="div1"></div>
元素.attributes[0].nodeType 就是数字2 找的就是id属性
元素.attributes[0].nodeValue 就是属性值 div1
元素.attributes[0].nodeName 就是节点属性名 id
注释节点要是获取值就是 xxx.childNodes[0].nodeValue 获取的就是注释里面的文字
子节点和兄弟节点
firstChild
她会包含文本节点和注释节点。在IE678下只包含元素节点,9以上全部包括
firstElementChild,IE678不支持,需要写兼容性
元素.firstElementChild只读属性
var Ofirst = ul.firstElementChild||firstChild;
if(Ofirst){
Ofirst.style.background = "red";
}else
{
window.alert("没有节点可以选择")
}
以上这段代码会报错。因为在oUl下面没有子元素节点,因此oUl.firstElementChild会返回为null,null不会传给变量oFirst,所以oFirst等于oUl.firstChild,而在标准浏览器下,oUl.firstChild是存在的,是一个文本节点,因此在下面的判断中,oFirst存在,因此走if语句的第一句,但是oFirst是文本节点,没有style可以设置,因此会报错。因此最好的做法是如下:
Ofirst.children[0].style["background"] = "red";
lastChild,lastElementChild
表示最后一个。同firstChild
nextSibling,previousSibling
元素.nextSibling下一个节点要是元素的是nextElementSibling
元素.previousSibling下一个节点要是元素的是previousSibling
父节点
元素.parentNode
offsetParent
找到当前元素最近的一个有定位的父节点
- 要是没有定位父级,默认就是body
offsetLeft ,offsetTop
元素.offsetLeft\offsetTop外边框到有定位父级的内边框的距离(找到最近的)
要是没有定位他找的就是距离body
getBoundingClientRect()
结果就是获取到这个元素的所有信息,返回的就是一个对象。然后在left,top之类的。这里特别注意的就是获取的值会根据滚动条变化的
offsetWidth,offsetHeight
- 元素.style.width :样式宽就是width值带单位
- clientWidth:样式宽+padding,不带单位
- offsetWidth:样式宽+padding+border
- 高度一样
操作元素的属性的多种方式
- 通过.点的形式 OText.value
- 通过中括号[]的形式:OText['value']当属姓名用变量表示,用中括号
getAttribute,setAttribute,removeAttribute
- 元素.getAttribute(属性名称) 获取指定元素指定属性的值
- 元素.setAttribute(属性名称) 给指定元素指定的属性设置值
- 元素.removeAttribute(属性名称) 移除指定元素的指定属性
PS:set/get与.的区别
1.用.和中括号没办法操作自定义属性,比如abc="234";getAttribute可以操作自定义属性
2.用.和[]的形式来获取src的时候,获取的是一长串绝对路径,但是在IE8以上以及标准浏览器中,用getAttribute(‘src’)可以获取到相对路径(但是在IE7及以下,获取的src还是绝对路径)
节点创建
document.createElement(标签名)
- 动态创建
- 不会直接显示在页面中
- 前面必须是document,不能是其他的
节点插入 appendChild()
父级.appendChild(要追加的元素)
- 方法
- 在指定父级子节点最后一个后面追加子元素
insertBefore
父级.insertBefore(新的元素.指定的被插入的元素)
var divnew = document.createElement("p");
divnew.innerHTML = "今天天气不错";
divnew.style["color"] = "yellow";
document.getElementById("div1").insertBefore(divnew,document.getElementsByClassName("abc")[0]);
相当于最外面是div1,然后在class是abc的前面插入p
- 在父级的指定子元素前面插入一个新的元素
- 在IE下要是第二个参数不存在会报错误
- 在其他浏览器下。要是第二个参数不存在。则会用appendChild()来添加
removeChild
父级.removeChild(要删除的节点)
replaceChild
父级.replaceChild(新节点,要替换的节点)
appendChild,insertBefore,replaceChild既可以操作静态节点,也可以操作动态节点
因为在JS里面没有addclassName方法,和removeclassName方法所以我们需要自己写
添加className方法
var liall = document.getElementsByTagName("li");
for(var i=0;i<liall.length;i++)
{
addClassName(liall[i],"on");
}
/*添加类*/
function addClassName(obj,className2)
{
if(obj.className=="")
{
obj.className="on";
}else
{
var Name = obj.getAttribute("class");
var arr = Name.split(" ");
var flag = false; //开关
for(var i=0;i<arr.length;i++)
{
if(arr[i]==className2) //当数组里面这个元素要是找到了证明他的存在,所以就没必要添加了
{
flag = true;
}
}
if(!flag) //表示全部都没找到
{
obj.className +=" "+className2;
}
}
}
/*添加类结束*/
移除className方法
var liall = document.getElementsByTagName("li");
for(var i=0;i<liall.length;i++)
{
removeClassName(liall[i],"on");
}
/*移除class类名*/
function removeClassName(obj,className2)
{
if(obj.className!="")
{
var string = obj.className; //获取到类名
var arr = string.split(" "); //切割成数组
var arrnew = [] ; //新的数组用来存储
for(var i=0;i<arr.length;i++)
{
if(arr[i] != className2)
{
arrnew.push(arr[i]);
}
}
obj.className = arrnew.join(" ");
}
}
/*移除class类名方法*/
表格操作
<table width="100%" id="tab1" border="1px">
<tr>
<td>1</td>
<td>leo</td>
<td>男</td>
<td><a href="javascript:;">删除</a></td>
</tr>
<tr>
<td>1</td>
<td>小美</td>
<td>女</td>
<td><a href="javascript:;">删除</a></td>
</tr>
</table>
因为没有写tbody所以他根本没办法获取到值
var oTab = document.getElementById('tab1');
alert(oTab.children[1].children[1].innerHTML);
//什么也弹不出来,提示显示oTab.children[1]未定义,这是因为如果在table中没有添加tbody的话,浏览器会自动隐形添加一个tbody出来。因此,写表格结构时,最好添加上tbody。
下面这个是最正规的写法
<table width="100%" id="tab1" border="1px">
<thead>
<tr>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>leo</td>
<td>男</td>
<td><a href="javascript:;">删除</a></td>
</tr>
<tr>
<td>1</td>
<td>小美</td>
<td>女</td>
<td><a href="javascript:;">删除</a></td>
</tr>
</tbody>
</table>
因为写了tbody便可以弹出来
var oTab = document.getElementById('tab1');
// alert(oTab.children[0].children[1].children[1].innerHTML); //这是就可以弹出“小美”
alert(oTab.tBodies[0].rows[1].cells[1].innerHTML); //弹出小美,更为直观
表格属性
-
tHead:表格头(DOM规定thead只能有一个)
-
tBodies表格正文(DOM规定tbody可以有多个)
-
tFoot表格尾(DOM规定只能有一个)
- rows:行
- cells:列
表格数据的操作
<table width="100%" id="tab1" border="1px">
<thead>
<tr>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>操作</th>
</tr>
</thead>
<tbody></tbody>
</table>
下面是动态创建表格
var data = [
{id: 1, username: 'leo', sex: '男'},
{id: 2, username: '小美', sex: '女'},
{id: 3, username: '王亮', sex: '男'},
{id: 4, username: '杜鹏', sex: '男'},
];
var oTab = document.getElementById('tab1');
var oTbody = oTab.tBodies[0];
for(var i=0; i<data.length; i++){ //表格的创建
var oTr = document.createElement('tr');
if(i%2 == 0){ //各行变色
oTr.style.background = 'white';
} else {
oTr.style.background = 'gray';
}
var oTd = document.createElement('td');
oTd.innerHTML = data[i].id;
oTr.appendChild(oTd);
oTd = document.createElement('td');
oTd.innerHTML = data[i].username;
oTr.appendChild(oTd);
oTd = document.createElement('td');
oTd.innerHTML = data[i].sex;
oTr.appendChild(oTd);
oTd = document.createElement('td');
// oTd.innerHTML = ' '; //如果单元格中的内容为空,那么在IE7及以下,这个td不会被创建,为了好看,给最后一列td里面添加一个空格,这样在IE7下,最后一列td也会被创建
oTr.appendChild(oTd);
var oA = document.createElement('a');
oA.innerHTML = '删除';
oA.href = 'javascript:;';
oA.onclick = function(){
oTbody.removeChild(this.parentNode.parentNode);
for(var i=0; i<oTbody.rows.length; i++){
if(i%2 == 0) {
oTbody.rows[i].style.background = 'white';
} else {
oTbody.rows[i].style.background = 'gray';
}
}
}
oTd.appendChild(oA);
oTbody.appendChild(oTr);
}
表单操作
<form id="form1">
<input type="text" name="text1" />
<input type="radio" name="sex" value="男" checked />男
<input type="radio" name="sex" value="女" />女
<input type="checkbox" name="a" value="html" checked />html
<input type="checkbox" name="a" value="css" />css
<input type="checkbox" name="a" value="javascript" />javascript
<select name="city">
<option value="">请选择城市</option>
<option value="北京">北京</option>
<option value="上海">上海</option>
</select>
<input type="button" value="按钮" name="btn" />
</form>
var oForm = document.getElementById('form1');
oForm.text1.onchange = function(){
alert(this.value); //注意,文本输入框onchange的触发,是在输入完毕之后,鼠标离开该文本框之后触发
}
oForm.sex[0].onchange = function(){
// alert(1);
// alert(this.value);
} //注意:oForm.sex其实是一个元素集合,因为name为sex的单选按钮有两个
oForm.a[0].onchange = function(){
alert(2);
}
// alert(oForm.city.value);
oForm.city.onchange = function(){
alert(this.value);
}
oForm.btn.onclick = function(){
//radio, checkbox 判断当前的选项是否被选中
//alert(oForm.sex[0].checked);
for(var i=0; i<oFrom.sex.length; i++){
if(oForm.sex[i].checked){
alert(oForm.sex[i].value + '被选中了');
} else {
alert(oForm.sex[i].value + '未被选中');
}
}
for(var i=0; i<oFrom.a.length; i++){
if(oForm.a[i].checked){
alert(oForm.a[i].value + '被选中了');
} else {
alert(oForm.a[i].value + '未被选中');
}
}
}
表单中的name来获取元素父级.name
window.alert(document.getElementById("form1").sex.value);
onchange事件
- onchange事件 :当值发生改变的时候触发
在type = text里面 :当光标离开的时候,内容有变化就触发
在type = radio/checkbox :
在点击下的时候只要值发生改变,就是触发
在非标准情况下焦点离开,值发生改变才触发 - select 一选择不同的项就触发
onsubmit
- onsubmit:当提交表单的时候触发
- submit():方法提交表单
代码见下
<form id="form1" action="http://www.baidu.com">
<input type="text" name="text1" />
<input type="text" name="text2" value="111" />
<input type="submit" name="dosubmit" value="提交" />
<input type="reset" name="doreset" value="重置" />
</form>
对应的JS代码
oForm.onsubmit = function(){
if(this.text1.value == ''){
alert('请输入内容');
return false; //如果没有在文本框中填写任何内容,就写return false,那么点击“提交”按钮,也不会提交到http://www.baidu.com上
}
}
/* 让页面等待一秒钟后自动提交
setTimeout(function(){
oForm.submit();
}, 1000)
onreset
PS:注意是重置,而不是清空,他的意思是恢复到默认值
onreset:当点击重置按钮的时候触发
oForm.onreset = function(){
var re = window.confirm("你确定要重置吗?")
return re;
}