文章目录
- 前言
- 一、DOM简介
- 1.1 DOM树
- 二、获取DOM元素
- 1、根据元素id获取-getElementById
- 2、根据元素名称获取元素对象-getElementsByTagName
- 3、H5新增API获取元素
- 4、获取body和html元素
- 三、DOM元素事件
- 四、操作DOM元素
- 1、改变元素内容
- 2、常用元素的属性操作
- 3、实践案例
- 4、操作DOM元素总结
- 5、元素自定义属性操作
- 五、DOM节点操作
- 5.1获取节点(父,子,兄节点)
- 5.2 创建节点
- 5.3 删除节点
- 5.4 复制节点
- 5.5 案例:动态生成表格
- 5.6 其他创建元素API
- 六、DOM重点核心总结
- 6.1 创建DOM元素
- 6.2 增
- 6.3 删
- 6.4 改
- 6.5 查
- 6.6 属性操作
- 6.7 事件操作
前言
本章围绕Web APIs进行介绍使用,都是些业务开发中常用的API(工具方法)。
本节内容:
- DOM简介
- DOM相关API获取元素
- DOM元素事件
- DOM元素属性
- DOM节点操作
- 创建DOM元素
一、DOM简介
DOM(Document Object Model)文档对象模型,是W3C组织推荐的处理可扩展标记语言(HTML或XML)的标准编程接口。(W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式等)
1.1 DOM树
- 文档:一个页面即一个文档,DOM中使用document表示,
- 元素:页面中所有标签都是元素,DOM中使用element表示。页面最外层由
<html>
根元素包裹,内部由各种标签(元素)- 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示
DOM把以上内容都看做是对象
二、获取DOM元素
获取DOM元素的方法:
- 根据元素id获取
- 根据元素标签名获取
- 通过H5新增的方法获取
- 特殊元素获取
1、根据元素id获取-getElementById
- MDN文档描述:getElementById
<!doctype html>
<html>
<head>
<title>getElementById example</title>
</head>
<body>
<p id="para">Some text here</p>
<button onclick="changeColor('blue');">blue</button>
<button onclick="changeColor('red');">red</button>
<script>
function changeColor(newColor) {
var elem = document.getElementById("para");
// 返回id为'elem'的元素对象
console.log(elem)
//打印元素对象的属性和方法
console.dir(elem)
elem.style.color = newColor;
}
</script>
</body>
</html>
2、根据元素名称获取元素对象-getElementsByTagName
- 注意:使用getElementByTagName获取到对应标签名的元素对象集合,以伪数组(没有pop,push等方法)的形式存储
- 因为得到的是一个元素对象的集合,所以想要操作具体元素可通过遍历方式
- 得到的元素是动态的
<body>
<ul>
<li>无序列表1</li>
<li>无序列表2</li>
<li>无序列表3</li>
<li>无序列表4</li>
</ul>
<script>
// 返回元素对象集合
var lis = document.getElementsByTagName('li')
console.log(lis)
// 获取某一个元素
console.log(lis[1])
</script>
</body>
- 获取某个标签内(父元素)指定标签名的子元素?
- API:element.getElementByTagName(‘标签名’);——element为指定的(父元素)(注意:父元素必须是单个对象)
<body>
<ul>
<li>无序列表</li>
<li>无序列表</li>
</ul>
<ol id="ol">
<li>ol下的li1</li>
<li>ol下的li2</li>
</ol>
<script>
let parentEl = document.getElementById('ol')
let lis = parentEl.getElementsByTagName('li')
console.log(lis)
</script>
</body>
3、H5新增API获取元素
- 根据class类名获取:getElementsByClassName(‘类名’):返回元素对象集合
- 根据选择器获取:document.querySelector(‘选择器名’) 返回指定选择器的第一个元素对象
<body>
<div class="box">这是Box</div>
<div class="box">这是BOX2</div>
<div id="box">这是id为box</div>
<script>
// 1、获取类名为box的元素——所有classname为box的元素
let box = document.getElementsByClassName("box");
// 2、根据选择器获取第一个匹配的元素——classname为box的第一个元素
let box1 = document.querySelector(".box");
let boxId = document.querySelector("#box");
// 3、获取指定选择器的所有元素——所有classname为box的元素
let boxArr = document.querySelectorAll(".box");
</script>
</body>
4、获取body和html元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// 1、获取body元素
let body = document.body
console.log(body)
// 2、获取html元素
let htmlEl = document.documentElement
console.log(htmlEl)
</script>
</body>
</html>
三、DOM元素事件
JS使我们有能力创建动态页面,而事件是可以被 JS监测到的行为。(触发-响应机制)网页中的每个元素都可以产生某些可以触发JS的事件,如:用户点击按钮时产生一个事件并触发执行相应的操作。
- 事件由三个部分组件(三要素):事件源,事件类型,事件处理程序。
<body>
<button id="btn">触发按钮</button>
<script>
// 1、获取事件源:事件被触发的对象(按钮)
var btn = document.getElementById("btn");
// 2、事件类型:如何触发,什么事件。如:鼠标点击(onclick),鼠标经过,键盘按下
// 3、事件处理程序:通过函数赋值的方式完成
btn.onclick = function () {
alert("点击事件触发");
};
</script>
</body>
事件注册的步骤:
- 获取事件源
- 绑定事件
四、操作DOM元素
JS的DOM操作可以改变网页内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等。注意以下都是属性:
- 1、改变元素的内容(innerText,innerHTML)
- 2、常用元素的属性操作
1、改变元素内容
- 改变内部文本内容: element.innerText,从element标签起始位到终止位的所有内容,但不会自动识别html标签,并去除空格及换行,只返回相应文本
- 改变内部html内容: element.innerHTML,从element标签起始位到终止位的所有内容,会自动识别html标签,同时保留空格及换行
<body>
<button>点击改变</button>
<div>text老内容</div>
<p>html老内容</p>
<script>
// 例:改变元素内容
// 1、获取要改变的元素
var btn = document.querySelector("button");
var div = document.querySelector("div");
var pEl = document.querySelector("p")
// 2、注册事件(当点击按钮时改变div的内容)
btn.onclick = function () {
// innerText和innerHTML两个API是可读写的,可通过
// 3、(写)改变元素内容(文本型)innerText(不会识别标签名,并去除空格和换行,只返回文本内容)
div.innerText = "新内容";
// 4、(写)改变元素内容(元素型)innerHTML(会自动识别标签名)
pEl.innerHTML = "<a href='https://baidu.com'>点击跳转百度</a>"
// 5、(读)
console.log(div.innerText,pEl.innerHTML)
};
</script>
</body>
2、常用元素的属性操作
1、src、href属性
2、id、alt、title属性
<body>
<button id="yz">杨紫</button>
<button id="zly">赵丽颖</button>
<p>示例1、修改图片src属性</p>
<img width="200px" title="杨紫" src="https://bkimg.cdn.bcebos.com/pic/2f738bd4b31c87017dbcaa562d7f9e2f0708ff7c?x-bce-process=image/watermark,image_d2F0ZXIvYmFpa2UxMTY=,g_7,xp_5,yp_5/format,f_auto" alt=""/>
<script>
// 示例:修改元素属性
// 1、获取元素
var yz = document.getElementById("yz")
var zly = document.getElementById("zly")
var img = document.querySelector("img")
// 2、绑定事件
yz.onclick=function(){
img.src="https://bkimg.cdn.bcebos.com/pic/2f738bd4b31c87017dbcaa562d7f9e2f0708ff7c?x-bce-process=image/watermark,image_d2F0ZXIvYmFpa2UxMTY=,g_7,xp_5,yp_5/format,f_auto"
img.title="杨紫"
}
zly.onclick=function(){
img.src="https://bkimg.cdn.bcebos.com/pic/e4dde71190ef76c6a7effa4aa344eafaaf51f3dec90a?x-bce-process=image/watermark,image_d2F0ZXIvYmFpa2UxODA=,g_7,xp_5,yp_5/format,f_auto"
img.title="赵丽颖"
}
</script>
</body>
3、实践案例
案例1:在不同的时间打开页面时,显示不同的问候语。如上午时打开,显示上午好,下午时打开显示下午好,晚上打开显示晚上好
<body>
<h1>问候语</h1>
<script>
// 根据不同访问时间,显示不同问题语
// 1、获取当前访问时间- DateAPI获取系统时间
let time = new Date();
let visitHours = time.getHours(); // 获取当前小时数
// 2、获取要改变的元素
let welcomeEle = document.querySelector("h1");
// 3、条件判定时间并改变
let welcomeStr = "";
if (visitHours > 0 && visitHours < 12) {
welcomeStr = "上午好!";
} else if (visitHours >= 12 && visitHours <= 18) {
welcomeStr = "下午好!";
} else if (visitHours > 18) {
welcomeStr = "晚上好!";
}
console.log(visitHours);
welcomeEle.innerHTML = welcomeStr;
</script>
</body>
- 案例2:修改表单属性
- 表单元素属性有:type、value, checked, selected, disabled
<body>
<button>按钮</button>
<input type="text" value="输入内容" />
<script>
// 改变输入框属性
// 1、获取元素
var btn = document.querySelector("button");
var input = document.querySelector("input");
// 2、绑定事件
btn.onclick = function () {
// 3、添加处理程序
// 改变表单内容,value属性
input.value = "改变内容了";
//禁用按钮-disabled属性
btn.disabled = true; // 或者this.disabled = true. this指定事件函数的调用者btn
};
</script>
</body>
- 案例3:输入框显示密码功能.(在业务中的密码输入框默认是不显示输入内容的,当点击某处时可显示输入的内容)
<body>
<button>显示</button>
<input type="password" value="123456" />
<script>
// 改变输入框属性
// 1、获取元素
var btn = document.querySelector("button");
var input = document.querySelector("input");
// 2、绑定事件
btn.onclick = function () {
if(this.innerText == '显示'){
input.type="text" // 1、通过修改input框的type属性,来设置显示隐藏。(type='password'时内容不可见,为text时内容可见)
this.innerText = '隐藏' // 对应改变按钮文案
}else{
input.type = "password"
this.innerText = '显示'
}
};
</script>
</body>
- 案例4:修改DOM元素样式属性-style(改变大小,颜色,位置等)
-
- element.style 行内样式操作
-
- element.className 类名样式操作(适合于样式较多功能复杂的情况)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
div {
width: 200px;
height: 200px;
background: pink;
}
</style>
</head>
<body>
<div id="box">这是个BOX</div>
<script>
// 示例:改变某一元素样式
// 注意:JS里的样式名采取驼峰命名法,如fontSize,backgroundColor; JS修改的style样式是行内样式,css权重较高
var box = document.getElementById("box");
box.onclick = function () {
// this指向事件调用者
this.style.background = "blue"; // 改背景色
this.style.width = '100px'; // 改宽度
};
</script>
</body>
</html>
- 案例6:显示隐藏二维码图片
- 思路:通过样式的显示隐藏属性实现,display:none隐藏元素,display:block显示元素
<body>
<div id="box">
<button class="btn">按钮</button>
<div class="qrcode">假设这是二维码</div>
</div>
<script>
// 示例:改变某一元素样式
var btn = document.querySelector(".btn");
var qrcode = document.querySelector(".qrcode");
var flag = 0;
btn.onclick = function () {
if (flag == 0) {
flag = 1;
qrcode.style.display = "none";
} else {
flag = 0;
qrcode.style.display = "block";
}
};
</script>
</body>
- 案例7:仿京东搜索框显示隐藏文本框内容
-
- 场景:输入框默认有值,当不输入时会直接搜索默认值。当聚焦时会清空输入框,输入搜索文案后会加深文字颜色
-
- 思路:文本框聚焦事件onfocus,失焦事件onblur
<body>
<input type="text" value="手机" />
<script>
// 示例:仿京东搜索框显示隐藏文本框内容
// 1、获取元素
let inputEl = document.querySelector("input");
inputEl.style.color="#999"
// 2、绑定事件
inputEl.onfocus = function () {
if (this.value == "手机") {
this.value = ""; // 聚焦时置空
this.style.color = "#333"; // 颜色加深
}
};
inputEl.onblur = function () {
if (this.value == "") {
this.value = "手机"; // 失焦时,若无值则恢复默认值
this.style.color = "#999"; // 默认值字体颜色为浅色
} else {
this.style.color = "#333";
}
};
</script>
</body>
- 案例9:通过className改变元素样式
- 注意:className修改元素类名时,会覆盖原先的类名。
- class是保留字,所以在js中使用className来对应元素类名选择器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.first {
width: 100px;
height: 100px;
background: pink;
color: #000;
}
.change {
background: purple;
color: #fff;
}
</style>
</head>
<body>
<div class="first">box</div>
<script>
let el = document.querySelector(".first")
el.onclick=function(){
// 获取原始className
let oldClassName = el.className
// 在原基础上添加新className,注意不同className之间需要空格隔开
this.className = oldClassName + ' change'
}
</script>
</body>
</html>
- 案例10:密码框验证信息
- 场景:用户输入密码位数应为8位以上,如输入不到8位报错显示(红字)
- 分析:判断事件是表单失去焦点事件onblur; 如果输入验证通过则显示绿色,不通过显示红色;因为控制变化的样式较多则使用className来改变样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.form-item{
display: flex;
align-items: center;
}
.msg{
font-size: 14px;
color: #999;
}
.wrong{
color: #f00;
}
.right{
color: green;
}
</style>
</head>
<body>
<div class="form-item">
<input type="text" class="input" value=""/>
<p class="msg">请输入8位以上密码</p>
</div>
<script>
let checkAll = document.getElementById("checkAll");
let allbox = document.querySelector("tbody").querySelectorAll(".checkbox");
// 全选功能
checkAll.onclick = function () {
let value = this.checked;
for (let i = 0; i < allbox.length; i++) {
let item = allbox[i];
console.log(item)
item.checked = value;
}
};
// 反选
for(let i=0;i<allbox.length;i++){
let item = allbox[i]
item.onclick=function(){
let allChecked = isAllChecked()
checkAll.checked = allChecked
}
}
function isAllChecked(){
let allChecked = true
for(let i=0;i<allbox.length;i++){
if(!allbox[i].checked){
allChecked = false
break; // 中断循环
}
}
return allChecked
}
</script>
</body>
</html>
- 案例11: 表格全选反选功能
- 全选:利用checkbox的checked属性进行全选赋值
- 反选:遍历子checkbox判定是否全部选中,控制全选框反选
4、操作DOM元素总结
5、元素自定义属性操作
1、获取自定义属性
- 获取属性值的两种方法:
- element.属性 : 获取元素内置属性
- element.getAttribute(属性名): 获取元素对应属性
- 两种获取元素属性方法的区别:
- element.属性只能获取元素自带的内置属性
- element.getAttribute(属性名): 可以获取内置以及自定义属性
2、设置元素属性值
- element.属性=值
- element.setAttribute(属性,值):针对自定义属性好用
3、移除自定义属性 - element.removeAttribute(属性)
4、在H5中通过dataset可获取属性名为’data-'开头的属性 - element.dataset.属性:仅适用于ie11以上浏览器,以data-开头的自定义属性
5、实用案例1:实现导航tab切换功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.tab-navs{
display: flex;
align-items: center;
}
li{
line-height: 30px;
color: #000;
border: 1px solid #ddd;
}
li.active{
background: pink;
}
.tab-contents .content{
display: none;
}
/* 默认显示首个内容 */
.content:first-child{
display: block;
}
</style>
</head>
<body>
<ul class="tab-navs">
<li data-index="0">导航1</li>
<li data-index="1">导航2</li>
<li data-index="2">导航3</li>
</ul>
<div class="tab-contents">
<div class="content">内容1</div>
<div class="content">内容2</div>
<div class="content">内容3</div>
</div>
<script>
let navs = document.querySelector(".tab-navs").querySelectorAll('li')
let contents = document.querySelectorAll(".content")
for(let i=0;i<navs.length;i++){
let nav = navs[i]
nav.onclick=function(){
// 设置导航变红
for(let j=0;j<navs.length;j++){
navs[j].className = ''
}
nav.className = 'active'
// 设置对应内容显示
let index = nav.getAttribute("data-index")
for(let k=0;k<contents.length;k++){
contents[k].style.display='none'
}
contents[index].style.display='block'
}
}
</script>
</body>
</html>
6、实例案例2:H5自定义属性获取
- 通过dataset属性集来获取元素自定义属性(命名以data-开头)
- 注意data-后有较长名称时,以驼峰名取值
<body>
<div class="box1" data-index="1">data1</div>
<div class="box2" data-list-name="2">data2</div>
<script>
let box1 = document.querySelector(".box1")
let box2 = document.querySelector(".box2")
let box1Attr = box1.getAttribute('data-index')
let box2Attr = box2.dataset['listName'] // 较长时以驼峰名取值
console.log(box1Attr,box2Attr)
</script>
</body>
五、DOM节点操作
5.1获取节点(父,子,兄节点)
- 什么是节点?:
- 页面中所有内容都是节点。(空格:文本节点)
- 节点属性:
- nodeName节点名,nodeType节点类型,nodeValue节点值。
- nodeType为1是元素节点,为2是属性节点,nodeType为3是文本节点包括文字,空格,换行等
- 节点层级:
- 常见层级关系有:父子兄层级关系
- 父节点:element.parentNode : 返回离element最近的父节点,如果找不到则返回null
- 子节点:element.childNodes: 返回元素的所有子节点,包括文本节点,元素节点等
- 子节点:element.children(非标准但都支持):返回所有的子元素节点
- 第一个子节点:element.firstChild:匹配文本,元素,属性节点
- 最后一个子节点:element.lastChild:匹配文本,元素,属性节点
- 第一个子元素节点:element.firstElementChild,只匹配第一个元素类型子节点,IE9以下
- 最后一个子元素节点:element.lastElementChild,只匹配最后一个元素类型子节点,IE9以下
- 兄弟节点(下一个兄弟节点):element.nextSibling, 下一个兄弟节点(包括元素节点,文本节点等)
- 兄弟节点(上一个兄弟节点):element.previousSibling
- 兄弟节点(下一个兄弟元素节点):element.nextElementSibling,IE9以上支持
- 兄弟节点(上一个兄弟元素节点):element.nextElementSibling,IE9以上支持
5.2 创建节点
- API:
- document.createElement(标签名):创建节点
- node.appendChild() 在元素内靠后插入添加节点
- node.insertBefore(child,指定元素): 在node内指定位置前插入
<body>
<ul>
<li>1</li>
</ul>
<script>
let ul = document.querySelector("ul")
let child = document.createElement("li")
child.innerHTML = 'child'
// 插入子节点-在元素最后
// ul.appendChild(child)
// 在指定位置插入节点
ul.insertBefore(child,ul.children[0])
</script>
</body>
5.3 删除节点
- node.removeChild(child)
<body>
<div class="box">
<input type="textarea" value="" />
<button class="btn">新增留言</button>
</div>
<ul class="lists">
</ul>
<script>
let textArea = document.querySelector("input");
let btn = document.querySelector(".btn");
let ul = document.querySelector(".lists");
btn.onclick = function () {
let text = textArea.value;
if (!text) {
alert("请先输入留言");
return;
}
let li = document.createElement("li");
li.innerHTML = text + "<a href='javascript:0;'>删除</a>";
ul.insertBefore(li, ul.children[0]);
textArea.value = ""
// 删除
let aLinks = document.querySelectorAll("a")
for(let i=0;i<aLinks.length;i++){
aLinks[i].onclick=function(){
ul.removeChild(this.parentNode)
}
}
};
</script>
</body>
5.4 复制节点
- node.cloneNode() : 返回调用方法的节点的一个副本
- 注意当不传参或传false时,只复制标签不复制里面的内容node.cloneNode(false)
- 深拷贝:参数传入true,标签以及内容都复制,node.cloneNode(true)
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<div class="box">box添加</div>
<script>
var ul = document.querySelector("ul")
var li = ul.children[0].cloneNode(true)
document.querySelector(".box").appendChild(li)
</script>
</body>
5.5 案例:动态生成表格
<body>
<table >
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script>
// 原始数据
let datas = [
{name:'张三',subject:'数学',score:98},
{name:'李四',subject:'数学',score:77},
{name:'王五',subject:'数学',score:88},
]
let tbody = document.querySelector("tbody")
// 批处理创建行
for(let i=0;i<datas.length;i++){
let tr = document.createElement("tr")
// 遍历对象属性添加单元格
for(let k in datas[i]){
let td = document.createElement("td")
// 为单元格添加属性值
td.innerHTML = datas[i][k]
tr.appendChild(td)
}
// 创建删除按钮
let delBtn = document.createElement("td")
delBtn.innerHTML = "<a herf='javascript:;'>删除</a>"
tr.appendChild(delBtn)
tbody.appendChild(tr)
}
let btns = document.querySelectorAll("a")
// 给所有按钮添加删除事件
for(let i=0;i<btns.length;i++){
btns[i].onclick=function(){
let td = this.parentNode
let tr = td.parentNode
tbody.removeChild(tr)
}
}
</script>
</body>
5.6 其他创建元素API
1、三种动态创建元素API区别
- document.write():直接将元素写入文档,如果页面已加载完毕才写入,会导致页面全部重绘
- innerHTML: 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构微微复杂
- createElement: 创建多个元素效率稍低,但是结构更清晰
- 不同浏览器上,innerHTML效率要比createElement更高
六、DOM重点核心总结
- 文档对象模型(DocumentObjectModel,简称 DOM),是W3C组织推荐的处理可扩展标记语言( HTML或者XML)的标准编程接口。
- W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式
6.1 创建DOM元素
- document.write()
- innerHTML
- document.createElement
6.2 增
- node.appendChild()
- node.insertBefore()
6.3 删
- node.removeChild(childNode)
6.4 改
主要修改dom的元素属性,内容,表单的值等
- 修改元素属性: src,href,title等
- 修改普通元素内容: innerHTML, innerText
- 修改表单元素: value, type,disabled等
- 修改元素样式: style , className
6.5 查
主要获取查询DOM的元素
- 老方法:getElementById,getElementsByClassName
- H5新方法:querySelector, querySelectorAll
- 节点操作获取元素: 父-parentNode,子-children,兄-previousElementSibling,nextElementSibling等
6.6 属性操作
主要针对自定义属性
- getAttribute: 获取dom属性值
- setAttribute:得到属性值
- removeAttribute:移除属性
6.7 事件操作
主要以鼠标事件为例:
- onclick:点击
- onmouseover: 鼠标移入
- onmouseout: 鼠标移出
- onfocus: 获取鼠标焦点
- onblur: 失去鼠标焦点
- onmousemove: 鼠标移动触发
- onmouseup: 鼠标绊
- onmousedown: 鼠标按下