文档逻辑结构
DOM基础概念、操作
DOM是什么
DOM全称为The Document Object Model,应该理解为是一个规范,定义了HTML和XML文档的逻辑结构和文档操作的编程接口。
文档逻辑结构
DOM实际上是以面向对象方式描述的对象模型,它将文档建模为一个个对象,以树状的结构组织(本文称之为“文档树”,树中的对象称为“节点”)。
每个文档包含1个document节点,0个或1个doctype节点以及0个或多个元素节点等。document节点是文档树的根节点。
如对于HTML文档,DOM 是这样规定的:
整个文档是一个文档节点
每个 HTML 标签是一个元素节点
包含在 HTML 元素中的文本是文本节点
每一个 HTML 属性是一个属性节点
注释属于注释节点
节点与文档内容是一一对应的关系,节点之间有层次关系。
例如下面的html文档:
<!DOCTYPE html>
<html>
<head>
<title>文档标题</title>
</head>
<body>
<a href="">我的链接</a>
<h1>我的标题</h1>
</body>
</html>
[图片上传失败...(image-2c214-1530240178333)]
nodeType
元素.nodeType:只读 属性 当前元素的节点类型
DOM节点的类型nodeType一种有12种,可以查看这里。
常用的节点类型包括:元素节点、文本节点、属性节点:
元素节点 ELEMENT_NODE:1
属性节点 ATTRIBUTE_NODE :2
文本节点 TEXT_NODE:3
<ul id="ul1" style="color: green">
<li>1111</li>
<li>1111</li>
<li>1111</li>
<li>1111</li>
</ul>
oUl = document.getElementById('ul1');
alert(oUl.nodeType); // 弹出1
alert(oUl.childNodes[0].nodeType); //弹出3
alert(oUl.attributes[0].nodeType); //弹出2
alert(oUl.attributes[0].name); //弹出'id'
alert(oUl.attributes.length); //弹出2
alert(oUl.attributes[0].value); //弹出'ul1'
attributes
元素.attributes:只读 属性 属性列表集合
具体代码可以查看NodeType中js代码中alert的部分。
DOM节点
childNodes \ children
获取第一级子元素
有兼容性问题(空白节点),nodeType属性
firstChild \ firstElementChild
获取子元素里的第一个
lastChild \ lastElementChild
获取子元素里的最后一个
childNodes
元素.childNodes:只读属性 子节点列表集合
childNodes至包含一级子节点,不包含后辈孙级以下的节点
childNodes的兼容性问题:
标准浏览器下:childNodes包含了文本和元素类型的节点,并且也会包含非法嵌套的子节点;
非标准浏览器下,至包含元素类型的节点,IE7及以下不包含非法嵌套的子节点
oUl = document.getElementById('ul1');
alert(oUl.childNodes.length); //在标准浏览器下弹出9;在IE6、7弹出4。因为标准浏览器下,文本元素(在这里是换行符)也包含在childNodes里面了。
for (var i=0; i<oUl.childNodes.length; i++){
oUl.childNodes[i].style.background = 'red'; //在标准浏览器下会报错,因为文本元素(这里是换行符)没有是没有style属性的。
}
//可以通过下面这种方式来解决:
for (var i=0; i<oUl.childNodes.length; i++){
if (oUl.childNodes[i].nodeType == 1) {
oUl.childNodes[i].style.background = 'red';
}
}
children
元素.children:只读 属性 子节点列表集合
标准下: 只包含元素类型的节点,并且包含非法嵌套的子节点
非标准下:只包含元素类型的节点,IE7及以下不包含非法嵌套的子节点
这样,如果把childNodes换为children的话,就不用进行nodeType的判断了。
for (var i=0; i<oUl.children.length; i++){
oUl.children[i].style.background = 'red';
}
子节点和兄弟节点的操作
firstChild
元素.firstChild:只读 属性 第一个子节点
标准下:firstChild会包含文本类型的节点
非标准下: 只包含元素节点
firstElementChild
元素.firstElementChild:只读 属性
标准下获取第一个元素类型节点的子节点
非标准浏览器不支持
因此要进行判断:
if (oUl.firstElementChild){
oUl.firstElementChild.style.background = 'red';
} else {
oUl.firstChild.style.background = 'red';
}
//更为简洁的写法:
var oFirst = oUl.firstElementChild || oUl.firstChild;
oFirst.style.background = 'red';
lastChild、lastElementChild
元素.lastChild
元素.lastElementChild 最后一个子节点
原理与firstChild
firstElementChild相似,不再赘述
nextSibling、previousSibling
元素.nextSibling
元素.nextElementSibling 下一个兄弟节点
元素.previousSibling
元素.previousElementSibling 上一个兄弟节点
父节点
parentNode
<ul id="ul1">
<li>1111 <a href="javascript:;">隐藏</a></li>
<li>2222 <a href="javascript:;">隐藏</a></li>
<li>3333 <a href="javascript:;">隐藏</a></li>
<li>4444 <a href="javascript:;">隐藏</a></li>
</ul>
var oA = document.getElementsByTagName('a');
for (var i=0; i<oA.length; i++){
oA[i].onclick = function(){
this.parentNode.style.display = 'none';
}
}
元素.parentNode: 只读 属性 只有一个 当前节点的父级节点
offsetParent
<head>
<style>
div {padding: 40px 50px;}
#div1 {background: red;}
#div2 {background: green;}
#div3 {background: orange;}
</style>
</head>
<body id="body1">
<div id="div1">
<div id="div2">
<div id="div3"></div>
</div>
</div>
</body>
var oDiv3 = document.getElementById('div3');
alert(oDiv3.parentNode.id); //弹出div2
alert(oDiv3.offsetParent.id); //弹出body1
上面的代码,如果给div1的style里面加上position: relative; 那么div3的offsetParent就变成了div1
元素.offsetParent:只读 属性 离当前元素最近的一个有定位的父节点
如果没有定位父级,默认是body
操作元素属性的多种方式
点的形式和中括号形式
通过.点的形式:oText.value
通过中括号[]的形式:oText[‘value’] (当属性名用变量来表示的时候,用中括号)
getAttribute、setAttribute、removeAttribute
元素.getAttribute(属性名称); 方法 获取指定元素的指定属性的值
元素.setAttribute(属性名称, 属性值); 方法 给指定元素指定的属性设置值
元素.removeAttribute(属性名称); 方法 移除指定的元素的指定的属性
set/get与用点.的区别:
用.和[]的形式无法操作元素的自定义属性;getAttribute可以操作元素的自定义属性
用.和[]的形式来获取src的时候,获取的是一长串绝对路径,但是在IE8以上以及标准浏览器中,用getAttribute(‘src’)可以获取到相对路径(但是在IE7及以下,获取的src还是绝对路径)
元素的创建操作
document.createElement();
document.createElement(标签名);
动态创建元素
不会直接显示在页面当中
前面必须是document,不能是其他
appendChild()
父级.appendChild(要追加的元素)
<!DOCTYPE html>
<html lang="en">
<head>
<style>
div {
padding: 40px 50px;
}
#div1 {
background: red;
position: relative;
}
#div2 {
background: green;
position: relative;
}
#div3 {
background: orange;
}
</style>
<script>
window.onload = function () {
var btn = document.getElementById('btn');
var ul = document.getElementById('ul');
btn.onclick = function () {
var li = document.createElement('li');//<li></li>
li.innerHTML = 'zhangsan';
ul.appendChild(li)
}
}
</script>
</head>
<body id="body1">
<button id="btn">娣诲姞li</button>
<ul id="ul">
</ul>
</body>
</html>
方法
在指定父级子节点最后一个后面追加子元素
insertBefore()
父级.insertBefore(新的元素,指定的被插入的元素);
方法
在父级的指定子元素前面插入一个新元素
在IE下,如果第二个参数的节点不存在,会报错
在其它标准浏览器下,如果第二个参数的节点不存在,则会以appendChild的方式进行添加
removeChild()
父级.removeChild(要删除的节点);
或者 元素.remove();
replaceChild()
父级.replaceChild(新节点、被替换节点) 替换子节点
appendChild,insertBefore,replaceChild可以操作静态节点,也可以操作动态生成的节点。
window.onload = function () {
var btn = document.getElementById('btn');
var ul = document.getElementById('ul');
var content = document.getElementById('text');
btn.onclick = function () {
var li = document.createElement('li');//<li></li>
li.innerHTML = content.value;
var a = document.createElement('a');
a.href = '#';
a.innerHTML = 'Delete';
a.onclick = function () {
this.parentNode.remove();
}
li.appendChild(a);
ul.appendChild(li);
}
}
表单操作
name
name:表单中可以通过name来获取元素:父级.name (该方法浏览器都兼容)
onchange事件
onchange事件:当值发生改变的时候触发
text:当光标离开的时候,如果内容有变化,就触发
radio/checkbox:
标准下点击的时候,只要值发生改变,就会触发;
非标准下,焦点离开的时候,如果值发生改变就触发
select:一选择不同的项,就触发
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<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>
<script>
var oForm = document.getElementById('form1');
oForm.text1.onchange = function(){
alert(this.value); //注意,文本输入框onchange的触发,是在输入完毕之后,鼠标离开该文本框之后触发
}
oForm.text1.oninput = function(){
condole.log(this.value);//输入一个字符,输出一个字符
}
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 + '未被选中');
}
}
}
</script>
</body>
</html>
表格操作
<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>
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>
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中规定tfoot只能有一个)
rows:行
cells:列
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table width="100%" id="tab1" border="1px">
<thead>
<tr>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
var data = [
{id: 1, username: 'leo', sex: '男'},
{id: 2, username: '小美', sex: '女'},
{id: 3, username: '王亮', sex: '男'},
{id: 4, username: 'zhangsan', 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');
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);
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
var data = [
{id: 1, username: 'leo', sex: '男',age:32},
{id: 2, username: '小美', sex: '女',age:32},
{id: 3, username: '王亮', sex: '男',age:32},
{id: 4, username: 'zhangsan', sex: '男',age:32},
{id: 5, username: 'dddd', sex: '男',age:32}
];
window.onload = function () {
// var obj = {id: 1, username: 'leo', sex: '男'};
// for(var p in obj)
// {
// alert(p);
// alert(obj[p]);
// }
var oTab = document.getElementById('tab1');
var oTbody = oTab.tBodies[0];
for(var i = 0; i < data.length; i++)
{
var tr = document.createElement('tr');//<tr></tr>
// var td1 = document.createElement('td');//<td></td>
// td1.innerText = data[i].id;
// tr.appendChild(td1);
// var td2 = document.createElement('td');//<td></td>
// td2.innerText = data[i].username;
// tr.appendChild(td2);
// var td3 = document.createElement('td');//<td></td>
// td3.innerText = data[i].sex;
// tr.appendChild(td3);
for(var p in data[i])//{id: 2, username: '小美', sex: '女'}
{
var td1 = document.createElement('td');//<td></td>
td1.innerText = data[i][p];
tr.appendChild(td1);
}
var td4 = document.createElement('td');//<td></td>
var a = document.createElement('a');
a.href = '#';
a.innerText = '删除';
a.onclick = function () {
this.parentNode.parentNode.remove();
for(var j = 0; j < oTbody.rows.length; j++)
{
if(j % 2 != 0)
{
oTbody.rows[j].style.backgroundColor = 'blue';
}
else
{
oTbody.rows[j].style.backgroundColor = 'white';
}
}
}
td4.appendChild(a);
tr.appendChild(td4);
oTbody.appendChild(tr);
}
for(var j = 0; j < oTbody.rows.length; j++)
{
if(j % 2 != 0)
{
oTbody.rows[j].style.backgroundColor = 'blue';
}
else
{
oTbody.rows[j].style.backgroundColor = 'white';
}
}
}
</script>
</head>
<body>
<table width="100%" id="tab1" border="1px">
<thead>
<tr>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!--<tr>-->
<!--<td>1</td>-->
<!--<td>leo</td>-->
<!--<td>男</td>-->
<!--</tr>-->
</tbody>
</table>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>购物车</title>
<meta charset="utf-8" />
<style type="text/css">
h1 {
text-align:center;
}
table {
margin:0 auto;
width:60%;
border:2px solid #aaa;
border-collapse:collapse;
}
table th, table td {
border:2px solid #aaa;
padding:5px;
}
th {
background-color:#eee;
}
</style>
<script>
var map = new Map();//key:商品名,tr:购物车中的商品数量
function compute_total_price() {
var tbodys = document.getElementById('goods');
var sum = 0;
for(var i = 0; i < tbodys.rows.length; i++)
{
sum += parseInt(tbodys.rows[i].cells[3].innerText);
}
document.getElementById('total').innerText = sum;
}
function decrease(obj) {
var count = parseInt(obj.nextElementSibling.value);
if(count > 1)
{
count--;
}
else
{
del(obj.parentNode.parentNode.cells[4].children[0]);
}
obj.nextElementSibling.value = count;
compute_price(obj.nextElementSibling);
}
function increase(obj) {
var count = parseInt(obj.previousElementSibling.value);
count++;
obj.previousElementSibling.value = count;
compute_price(obj.previousElementSibling);
}
function del(obj) {
map.delete(obj.parentNode.parentNode.cells[0].innerText);
obj.parentNode.parentNode.remove();
compute_total_price();
}
function compute_price (obj) {
var count = parseInt(obj.value);
var price = parseInt(obj.parentNode.previousElementSibling.innerText);
var total_price = price * count;
obj.parentNode.nextElementSibling.innerText = total_price;
compute_total_price();
}
window.onload = function () {
var goods = document.getElementById('goods_list');
var tbody = document.getElementById('goods');
var inputs = goods.getElementsByTagName('input');
for(var i = 0; i < inputs.length;i++)
{
inputs[i].onclick = function () {
var good_name = this.parentNode.parentNode.cells[0].innerText;
if(map.has(good_name))
{
var tr = map.get(good_name);
var str_count = tr.cells[2].children[1].value;
var count = parseInt(str_count) + 1;
tr.cells[2].children[1].value = count;
compute_price(tr.cells[2].children[1]);
}
else
{
var good_price = this.parentNode.parentNode.cells[1].innerText;
var cart_item = `
<td>${good_name}</td>
<td>${good_price}</td>
<td align="center">
<input type="button" value="-" onclick="decrease(this)"/>
<input type="text" size="3" value="1"/>
<input type="button" value="+" onclick="increase(this)"/>
</td>
<td>${good_price}</td>
<td align="center">
<input type="button" value="x" onclick="del(this)"/>
</td>
`;
var tr = document.createElement('tr')
tr.innerHTML = cart_item;
tbody.appendChild(tr);
map.set(good_name,tr);
compute_total_price();
}
}
}
}
</script>
</head>
<body>
<h1>真划算</h1>
<table id="goods_list">
<tr>
<th>商品</th>
<th>单价(元)</th>
<th>颜色</th>
<th>库存</th>
<th>好评率</th>
<th>操作</th>
</tr>
<tr>
<td>罗技M185鼠标</td>
<td>80</td>
<td>黑色</td>
<td>893</td>
<td>98%</td>
<td align="center">
<input type="button" value="加入购物车" />
</td>
</tr>
<tr>
<td>微软X470键盘</td>
<td>150</td>
<td>黑色</td>
<td>9028</td>
<td>96%</td>
<td align="center">
<input type="button" value="加入购物车" />
</td>
</tr>
<tr>
<td>洛克iphone6手机壳</td>
<td>60</td>
<td>透明</td>
<td>672</td>
<td>99%</td>
<td align="center">
<input type="button" value="加入购物车" />
</td>
</tr>
<tr>
<td>蓝牙耳机</td>
<td>100</td>
<td>蓝色</td>
<td>8937</td>
<td>95%</td>
<td align="center">
<input type="button" value="加入购物车" />
</td>
</tr>
<tr>
<td>金士顿U盘</td>
<td>70</td>
<td>红色</td>
<td>482</td>
<td>100%</td>
<td align="center">
<input type="button" value="加入购物车" />
</td>
</tr>
</table>
<h1>购物车</h1>
<table>
<thead>
<tr>
<th>商品</th>
<th>单价(元)</th>
<th>数量</th>
<th>金额(元)</th>
<th>删除</th>
</tr>
</thead>
<tbody id="goods">
</tbody>
<tfoot>
<tr>
<td colspan="3" align="right">总计</td>
<td id="total"></td>
<td></td>
</tr>
</tfoot>
</table>
</body>
</html>