1. DOM document
DOM全称document object model (文档对象模型)
- 文档:整个HTML文件就是一个文档;
- 对象:HTML文件中的每个节点都在JS中是一个对象;
- 模型:JS使用模型来表示各个对象之间的关系;
JS中有宿主对象document,它是window对象的属性,也就是文档对象本身;
nodeName | nodeType | nodeValue | |
---|---|---|---|
文档节点 | #document | 9 | null |
元素节点 | 标签名 | 1 | null |
属性节点 | 属性名 | 2 | 属性值 |
文本节点 | #text | 3 | 文本文件 |
注释是注释节点。
常用方法: 菜鸟-HTML DOM Document 对象
1.1 DOM 常用查询修改元素
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> DOM 常用查询修改元素</title>
<style>
div {
border: 1px solid black;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div><p>这是p[0]</p></div>
<p class="example">p[1] class="example"</p>
<p class="changeClassnTag">p[2] class="changeClassnTag"</p>
<div><p >这是p[3]</p></div>
<h1>一个 H1 元素</h1>
<h2>一个 H2 元素</h2>
<div>一个 DIV 元素</div>
<p>p[4],包含了 <span style="color:brown;">span</span> 元素。 </p>
<a href="http://www.disney.com" target="_blank">a[target]-disney.com</a>
<br>
<br>
<button onclick="queSel()">按钮-改变p[0]背景颜色</button>
<button onclick="queSel2()">按钮-改变第一个class="example"元素</button>
<br>
<button onclick="queSel3()">按钮-改变第一个class="changeClassnTag"的'p'元素</button>
<button onclick="queSel4()">按钮-改变第一个a[target]</button>
<br>
<button onclick="queSelAll1()">按钮-修改父元素为 div 的所有 p 元素的背景颜色。</button>
<button onclick="queSelAll2()">按钮-修改h2, div 和 span 元素的背景颜色。</button>
<br>
<p id="demo">p[4],单击按钮来改变这一段中的文本。</p>
<button onclick="changeIdText()">根据id改变按钮文本</button>
<button onclick="changeTagText()">根据tag[指定第几个p元素]改变按钮文本</button>
<br>
猫:(name="x")
<input name="x" type="radio" value="猫">
狗:(name="x")
<input name="x" type="radio" value="狗">
<br>
<input type="button" onclick="getElements()" value="查询名称为'x'的元素数量?">
<br>
<script type="text/javascript" >
function changeIdText(){
// getElementById() 通过ID值获取对应的节点,改变其对应的文字内容
document.getElementById("demo").innerHTML="kk";
};
function getElements(){
// getElementsByName() 方法可返回带有指定名称的对象的集合
var x=document.getElementsByName("x");
alert(x.length); //返回数量
}
function changeTagText(){
// getElementsByTagName() 方法可返回带有指定标签名的对象的集合。
// 参数值 "*" 返回文档的所有元素。
// 传递给 getElementsByTagName() 方法的字符串可以不区分大小写
document.getElementsByTagName("P")[5].innerHTML="Hello World";
};
// getElementsByClassName() 方法可返回带有指定class名称的对象的集合
// getElementsByClassName() 只支持IE8以上, IE8及以下可以用 querySelector() 替代
// querySelector() 通过CSS选择器返回一个节点,当能匹配多个节点时,返回满足匹配的第一个节点
function queSel() {
// 获取文档中第一个 <p> 元素:
document.querySelector("p").style.backgroundColor = "red";
}
function queSel2() {
// 代替 getElementsByClassName()
// 获取文档中 class="example" 的第一个元素:
document.querySelector(".example").style.backgroundColor = "green";
}
function queSel3() {
// 获取文档中 class="changeClassnTag" 的第一个 <p> 元素:
document.querySelector("p.changeClassnTag").style.backgroundColor = "orange";
}
function queSel4() {
// 获取文档中有 "target" 属性的第一个 <a> 元素:
document.querySelector("a[target]").style.border = "10px solid red";
}
// querySelectorAll() 方法返回文档中匹配指定 CSS 选择器的所有元素,返回 NodeList 对象(将符合条件的元素封装成数组,即使只有一个元素也是数组)。
// NodeList 对象表示节点的集合。可以通过索引访问,索引值从 0 开始。
// 可以使用 NodeList 对象的 length 属性来获取匹配选择器的元素属性,然后遍历所有元素,从而修改信息。
function queSelAll1() {
// 查找每个父元素为 <div> 的 <p> 元素,并为其设置背景颜色:
var x = document.querySelectorAll("div > p");
var i;
for (i = 0; i < x.length; i++) {
x[i].style.backgroundColor = "red";
}
}
function queSelAll2() {
// 给文档中所有的 <h2>, <div> 和 <span> 元素设置背景颜色:
var x = document.querySelectorAll("h2, div, span");
var i;
for (i = 0; i < x.length; i++) {
x[i].style.backgroundColor = "purple";
}
}
</script>
</body>
</html>
2. DOM 事件 和 文档的加载
菜鸟-HTML DOM 事件
事件:用户与浏览器的交互行为,如鼠标点击、窗口关闭等;
使用:
- 在事件对应的属性中写入JS代码,使得在事件被触发时代码执行;
——结构与行为耦合,不使用;- 为按钮的对应时间绑定处理函数的形式来响应事件;
——当事件被触发的时候,其对应的函数才会被调用;推荐使用;
文档加载顺序:
- 浏览器加载HTML文件时是自上向下加载,读到一行执行一行。因此当js代码写在页面上面时,在代码执行时,页面还没有加载,DOM对象也没加载,可能出现无法获取到DOM对象的情况;
- 如果要写在上面,为window绑定一个onload事件。
onload: 一张页面或一幅图像完成加载。
// 写在head里面,因为文档加载顺序,可能报错:uncaught TypeError: Cannot set property 'onclick' of null;
// 1. 写在body;
<button id="btn"></button>
<script>
// 获取id为btn的按钮
var btn = document.getElementById("btn");
// 绑定一个单击事件,称为单击响应函数
btn.onclick = function(){
alert("a");
}
</script>
// 2. 为window绑定一个onload事件
<script>
window.onload = function(){
alert("a");
}
</script>
3. DOM 元素节点
菜鸟-HTML DOM 元素对象
使用:
- element.getElementsByTagName(tagname):可返回带有指定标签名的对象的集合;
- element.childNodes 返回元素子节点的 NodeList,将代码里面的换行也会算成子节点;
- element.children 获取当前元素的子元素,不算空行;
- element.firstChild 返回元素的首个子节点;
- element.lastChild 返回元素的最后一个子节点;
- element.firstElementChild 返回元素的首个子元素,但是不支持IE8及以下;
- element.lastElementChild 返回元素的最后一个子元素,但是不支持IE8及以下;
- element.parentNode 返回元素的父节点;
- element.previousSibling 返回位于相同节点树层级的前一个元素,即当前元素节点的前一个兄弟节点;
- element.nextSibling 返回位于相同节点树层级的下一个节点;
- element.previousElementSibling 当前元素节点的前一个兄弟元素节点, 仅支持IE8以上;
- element.nextElementSibling 获取当前元素节点的后一个兄弟元素节点, 仅支持IE8以上
4. DOM 其他查询
ducument.body === document.getElementByTagName(“body”)[0]; // 返回属性body
html = document.documentElement; // 返回html
all = document.all; //返回所有元素,包括html, head, div等,可以通过all.length遍历;
5. 应用
5.1 图片切换
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
#outer{
width: 500px;
margin: 50px auto;
padding: 10px;
background-color: aquamarine;
/* 文本居中 */
text-align: center;
}
</style>
<script type="text/javascript" >
window.onload = function(){
var prev = document.getElementById("prev");
var next = document.getElementById("next");
var img = document.getElementsByTagName("img")[0];
var imgArr = ["img/pic1.jpg", "img/pic2.jpg", "img/pic3.jpg"];
var index = 0;
var info = document.getElementById("info");
info.innerHTML="一共有"+imgArr.length+"张图片,现在是第"+(index+1)+"张";
prev.onclick = function(){
index--;
if(index < 0)
{
index = imgArr.length - 1 ;
}
img.src = imgArr[index];
info.innerHTML="一共有"+imgArr.length+"张图片,现在是第"+(index+1)+"张";
}
next.onclick = function(){
index++;
if(index > imgArr.length - 1 )
{
index = 0;
}
img.src = imgArr[index];
info.innerHTML="一共有"+imgArr.length+"张图片,现在是第"+(index+1)+"张";
}
}
</script>
</head>
<body>
<div id="outer">
<p id="info">一共有3张图片,现在是第1张</p>
<img src="img/pic1.jpg" alt="fall" width="450px" height="300px"/>
<br>
<button id="prev">上一张</button>
<button id="next">下一张</button>
</div>
</body>
</html>
5.2 DOM增删改
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> Dom 增删改</title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
#total{
background-color: #918b8b;
width: 500px;
height: auto;
margin-left: 15%;
margin-top: 5%;
float: left;
text-align: center;
}
#inner{
text-align: center;
}
#city li{
display: inline-block;
width: 100px;
height: 30px;
background-color: cornflowerblue ;
line-height: 30px;
color: white;
border: 1px solid cornflowerblue;
border-radius: 8px ;
/* margin-right: 10px; */
margin-left: 10px;
}
#btnList{
text-align: center;
float: right;
margin-right: 25%;
margin-top: 5%;
}
</style>
<script type="text/javascript">
window.onload = function(){
// 创建一个"广州"节点,添加到#city下面
myClick("btn01",function(){
// document.createElement(nodename) 通过指定名称创建一个元素
// 创建li元素节点
var li = document.createElement("li");
// Document.createTextNode(data: string)
// 创建广州文本节点
var gzText = document.createTextNode("广州");
// appendChild(node: Text)
// 将gzText设置成li的子节点
li.appendChild(gzText);
// 获取id为city的节点
var city = document.getElementById("city");
// 将广州添加到city底下
city.appendChild(li);
});
// 将"广州"插入到#bj前面
myClick("btn02",function(){
var li = document.createElement("li");
var gzText = document.createTextNode("广州");
li.appendChild(gzText);
var bj = document.getElementById("bj");
var city = document.getElementById("city");
// node.insertBefore(newnode,existingnode)
// newnode 节点对象 必须。要插入的节点对象
// existingnode 节点对象 必须。要添加新的节点前的子节点。
city.insertBefore(li,bj);
});
// 使用"广州"节点替换#sh节点
myClick("btn03",function(){
var li = document.createElement("li");
var gzText = document.createTextNode("广州");
li.appendChild(gzText);
var sh = document.getElementById("sh");
var city = document.getElementById("city");
// node.replaceChild(newnode,oldnode)
// newnode Node 对象 必须。你要插入的节点对象。
// oldnode Node object 必须。你要移除的节点对象。
city.replaceChild(li, sh);
});
// 删除#bj节点
myClick("btn04",function(){
var bj = document.getElementById("bj");
var city = document.getElementById("city");
// node.removeChild(node)
// node 节点对象 必须。 你要移除的节点对象。
// node.parentNode 返回某节点的父节点。 如果指定的节点没有父节点则返回 null 。
bj.parentNode.removeChild(bj);
});
// 读取#city内的HTML代码
myClick("btn05",function(){
var city = document.getElementById("city");
alert(city.innerHTML);
});
// 修改#bj内的HTML代码
myClick("btn06",function(){
var bj = document.getElementById("bj");
bj.innerHTML = "杭州";
});
// 设置#city内的HTML代码,添加"深圳"
myClick("btn07",function(){
var city = document.getElementById("city");
// 直接使用innerHTML完成对DOM的增删改操作
// 修改了整个city标签的代码(先删除后添加),变动比第一种方法大(直接添加)
// city.innerHTML += "<li>深圳</li>";
// 一般情况下会使用两种方式相结合
var li = document.createElement("li");
li.innerHTML = "深圳";
city.appendChild(li);
});
}
function myClick(idStr, fun){
var btn = document.getElementById(idStr);
btn.onclick = fun;
}
</script>
</head>
<body>
<div id="total">
<div class="inner">
<p>你喜欢哪个城市?</p>
<ul id="city">
<li id="bj"> 北京</li>
<li id="sh">上海</li>
<li>东京</li>
<li>首尔</li>
</ul>
</div>
</div>
<div id="btnList">
<div><button id="btn01">创建一个"广州"节点,添加到#city下面</button></div><br>
<div><button id="btn02">将"广州"插入到#bj前面</button></div><br>
<div><button id="btn03">使用"广州"节点替换#sh节点</button></div><br>
<div><button id="btn04">删除#bj节点</button></div><br>
<div><button id="btn05">读取#city内的HTML代码</button></div><br>
<div><button id="btn06">修改#bj内的HTML代码</button></div><br>
<div><button id="btn07">设置#city内的HTML代码,添加"深圳"</button></div>
</div>
</body>
</html>
JS点击超链接默认跳转页面, 可以用
return false;
回避;
confirm("确认删除吗?");
弹窗 选择"确认"(返回true)/“取消”(返回false);
5.2 DOM操作CSS
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>DOM操作CSS</title>
<style type="text/css">
#box1{
width: 100px;
height: 100px;
background-color: rgb(30, 26, 148);
}
#box2 {
padding: 100px;
background-color: #bfa;
}
#box4 {
width: 200px;
height: 300px;
background-color: #bfa;
overflow: auto;
}
#box5 {
width: 450px;
height: 600px;
background-color: yellow;
}
#box6 {
width: 100px;
height: 100px;
background-color: rgb(140, 74, 176);
padding: 10px;
border: 10px solid rgb(0, 221, 255);
}
</style>
<script type="text/javascript">
window.onload = function(){
/*
* 点击按钮以后,修改box1的大小
*/
// 获取box1
var box1 = document.getElementById("box1");
// 为按钮绑定单击响应函数
var btn01 = document.getElementById("btn01");
btn01.onclick = function(){
//修改box1的宽度
/*
* 通过JS修改元素的样式:
* 语法:元素.style.样式名 = 样式值
*
* 注意:如果CSS的样式名中含有-,
* 这种名称在JS中是不合法的比如background-color
* 需要将这种样式名修改为驼峰命名法
* 去掉-,然后将-后的字母大写,如backgroundColor
*
* 我们在"html标签内部通过style属性来设置元素的样式"都是内联/行内样式,
* 而内联样式有较高的优先级,所以通过JS修改的样式往往会立即显示
*
* 但是如果在样式表中写了!important,则此时样式会有最高的优先级,
* 即使通过JS也不能覆盖该样式,此时将会导致JS修改样式失效
* 所以尽量不要为样式添加!important
*
*/
box1.style.width = "300px";
box1.style.height = "300px";
box1.style.backgroundColor = "yellow";
};
// 点击按钮2以后,读取元素的样式
var btn02 = document.getElementById("btn02");
btn02.onclick = function(){
//读取box1的样式
/*
* 语法:元素.style.样式名
*
* 能通过style属性设置和读取的都是内联样式(写在style, 而不是样式表)
* --无法读取样式表中的样式
*
*/
//alert(box1.style.height);
alert(box1.style.width);
};
var btn03 = document.getElementById("btn03");
btn03.onclick = function()
{
/*
* 获取元素的当前显示的样式
* 语法:元素.currentStyle.样式名
* 它可以用来读取当前元素正在显示的样式
* 如果当前元素没有设置该样式,则获取它的默认值
*
* currentStyle只有IE浏览器支持,其他的浏览器都不支持
*/
//alert(box1.currentStyle.width);
//box1.currentStyle.width = "200px";
//alert(box1.currentStyle.backgroundColor);
var w = getStyle(box1,"width");
alert(w);
}
var btn04 = document.getElementById("btn04");
var box4 = document.getElementById("box4");
var box6 = document.getElementById("box6");
btn04.onclick = function(){
/*
* clientWidth
* clientHeight
* - 这两个属性可以获取元素的可见宽度和高度
* - 这些属性都是不带px的,返回都是一个数字,可以直接进行计算
* - 会获取元素宽度和高度,包括内容区和内边距
* - 这些属性都是只读的,不能修改
*/
// alert(box6.clientWidth);
// alert(box6.clientHeight); // 120
// box6.clientHeight = 300; // 无效
// alert(box6.clientHeight); // 120
/*
* offsetWidth
* offsetHeight
* - 获取元素的整个的宽度和高度,包括内容区、内边距和边框
*/
// alert(box6.offsetWidth);
/*
* offsetParent
* - 可以用来获取当前元素的定位父元素
* - 会获取到离当前元素最近的开启了定位的祖先元素
* 如果所有的祖先元素都没有开启定位,则返回body
*/
var op = box6.offsetParent;
// alert(op.id); //box2
/*
* offsetLeft
* - 当前元素相对于其定位父元素的水平偏移量
* offsetTop
* - 当前元素相对于其定位父元素的垂直偏移量
*/
// alert(box6.offsetLeft); // 100
/*
* scrollWidth
* scrollHeight
* - 可以获取元素整个滚动区域的宽度和高度
*/
// alert(box4.clientHeight); // 283 可见高度
// alert(box4.scrollHeight); // 600 整个高度
/*
* scrollLeft
* - 可以获取水平滚动条滚动的距离
* scrollTop
* - 可以获取垂直滚动条滚动的距离
*/
// alert(box4.scrollLeft);
// alert(box4.scrollTop);
//alert(box4.clientHeight); // 283
// 当满足scrollHeight - scrollTop == clientHeight
// 当满足全部高度 - 垂直滚动条滚动高度 = 可见高度
// 说明垂直滚动条滚动到底了
// 当满足scrollWidth - scrollLeft == clientWidth
// 当满足全部宽度 - 水平滚动条滚动宽度 = 可见宽度
// 说明水平滚动条滚动到底
alert(box4.scrollHeight - box4.scrollTop); // 600
}
};
/*
* 定义一个函数,用来获取指定元素的当前的样式
* 参数:
* obj 要获取样式的元素
* name 要获取的样式名
*/
function getStyle(obj , name){
if(window.getComputedStyle){
// window.getComputedStyle(element, pseudoElement) 用于获取指定元素的 CSS 样式
// element: 必需,要获取样式的元素。
// pseudoElement: 可选,伪类元素,当不查询伪类元素的时候可以忽略或者传入 null。
// 获取的样式是元素在浏览器中最终渲染效果的样式, 可以通过对象.样式名来读取样式
// 正常浏览器的方式,具有getComputedStyle()方法
return getComputedStyle(obj , null)[name];
}else{
// IE8的方式,没有getComputedStyle()方法
return obj.currentStyle[name];
}
// return window.getComputedStyle?getComputedStyle(obj , null)[name]:obj.currentStyle[name];
}
</script>
</head>
<body id="body">
<button id="btn01">改变样式</button>
<button id="btn02">获取样式</button>
<button id="btn03">获取样式2</button>
<br /><br />
<div id="box1"></div>
<br /><br />
<button id="btn04">点我一下</button>
<br /><br />
<div id="box4">
<div id="box5"></div>
</div>
<br /><br />
<div id="box3">
<div id="box2" style="position: relative;">
<div id="box6"></div>
</div>
</div>
</body>
</html>
5.3 DOM增删改表单
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>添加删除记录练习</title>
<link rel="stylesheet" type="text/css" href="ex_2_style/css.css" />
<script type="text/javascript">
function removeTr(){
// this --指向 aEles[i].onclick 的 aEles[i]
// 但是不能直接用aEles[i]
// 原因: 在接收到aEles[i].onclick时, for循环已经遍历完
// alert(this); // file:///E:/Desktop/JavaLearn/JS_Learn/jsBasic/deleteEmp?id=001
// alert(aEles[i]); // 报错
// var trNode = aEles[i].parentNode.parentNode; // 报错
// 结构,tr底下有4个td, 其中第四个为响应onclick的的aEles[i]
// 获取当前this的parentNode-tr节点的parentNode-td节点
var trNode = this.parentNode.parentNode;
var tds = trNode.getElementsByTagName("td");
var nameStr = tds[0].firstChild.nodeValue; //第一个td为name 用于弹窗确认
// 弹窗确定
var flag = confirm("真的要删除" + nameStr + "的信息吗?");
if(flag){
trNode.parentNode.removeChild(trNode);
}
// 取消默认href跳转页面行为
return false;
}
window.onload = function(){
// 目标1:点击Delete删除记录
var aEles = document.getElementsByTagName("a");
for(var i = 0;i < aEles.length;i++){
aEles[i].onclick = removeTr;
// alert(i); // 0 1 2 然后在进入函数removeTr
}
// 目标2:点击Submit增加记录
var subBtn = document.getElementById("addEmpButton");
subBtn.onclick = function(){
var nameText = trim(document.getElementById("empName").value);
var emailText = trim(document.getElementById("email").value);
var salaryText = trim(document.getElementById("salary").value);
document.getElementById("empName").value = nameText;
document.getElementById("email").value = emailText;
document.getElementById("salary").value = salaryText;
if(nameText == "" || emailText == "" || salaryText == ""){
alert("您输入的内容不完整");
return ;
}
// 组装节点
var nameTd = document.createElement("td");
var emailTd = document.createElement("td");
var salaryTd = document.createElement("td");
var aTd = document.createElement("td");
nameTd.appendChild(document.createTextNode(nameText));
emailTd.appendChild(document.createTextNode(emailText));
salaryTd.appendChild(document.createTextNode(salaryText));
// 创建a标签,并添加href,封装响应函数
var aNewEle = document.createElement("a");
aNewEle.href = "deleteEmp?id=XXX";
aNewEle.appendChild(document.createTextNode("Delete"));
aNewEle.onclick = removeTr;
aTd.appendChild(aNewEle);
// 将td节点添加到tr
var trNode = document.createElement("tr");
trNode.appendChild(nameTd);
trNode.appendChild(emailTd);
trNode.appendChild(salaryTd);
trNode.appendChild(aTd);
// 将tr添加到table employeeTable
var empTable = document.getElementById("employeeTable");
empTable.appendChild(trNode);
}
function trim(str){
var reg = /^\s*|\s*$/g;
return str.replace(reg,"");
}
}
</script>
</head>
<body>
<table id="employeeTable">
<tr>
<th>Name</th>
<th>Email</th>
<th>Salary</th>
<th> </th>
</tr>
<tr>
<td>Tom</td>
<td>tom@tom.com</td>
<td>5000</td>
<td><a href="deleteEmp?id=001">Delete</a></td>
</tr>
<tr>
<td>Jerry</td>
<td>jerry@sohu.com</td>
<td>8000</td>
<td><a href="deleteEmp?id=002">Delete</a></td>
</tr>
<tr>
<td>Bob</td>
<td>bob@tom.com</td>
<td>10000</td>
<td><a href="deleteEmp?id=003">Delete</a></td>
</tr>
</table>
<div id="formDiv">
<h4>添加新员工</h4>
<table>
<tr>
<td class="word">name: </td>
<td class="inp">
<input type="text" name="empName" id="empName" />
</td>
</tr>
<tr>
<td class="word">email: </td>
<td class="inp">
<input type="text" name="email" id="email" />
</td>
</tr>
<tr>
<td class="word">salary: </td>
<td class="inp">
<input type="text" name="salary" id="salary" />
</td>
</tr>
<tr>
<td colspan="2" align="center">
<button id="addEmpButton" value="abc">
Submit
</button>
</td>
</tr>
</table>
</div>
</body>
</html>