文档对象模型(Document Object Model
,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。
W3C
已经定义了一系列的 DOM
接口,通过这些 DOM
接口可以改变网页的内容、结构和样式。
document
表示;element
表示;node
表示。DOM
中看做对象。在实际开发中,DOM
主要用来操作元素,获取页面元素主要有以下几种方式:
ID
获取;HTML5
新增的方法获取;getElementById()
方法:获取带有 ID
的元素对象;document.getElementById('id');
console.dir()
打印出获取的元素对象,以查看对象的属性和方法。
getElementsByTagName
() 方法可返回带有指定标签名的对象的集合。
document.getElementsByTagName('标签名');
注:
1). 得到的是对象的集合,所以在操作里面的元素前需要遍历;
2). 得到元素对象是动态的;
3). 如果获取不到元素,则返回空的伪数组(获取不到对象)。
同样,也可以获取某个元素(父元素)内部所有指定标签名的子元素:
element.getElementsByTagName('标签名')
注:父元素必须是单个对象(必须指明是哪一个元素对象). 获取的时候不包括父元素自己。
// 1、根据类名返回元素对象集合:
document.getElementsByClassName('类名');
// 2、根据指定选择器返回第一个元素对象:
document.querySelector('选择器');
// 3、根据指定选择器返回所有元素对象:
document.querySelectorAll('选择器');
注意:
querySelector
和 querySelectorAll
里面的选择器需要加符号,示例如下:
document.querySelector('#nav');
document.body // 返回body元素对象。
document.documentElement // 返回html元素对象。
JavaScript 能创建动态页面,而事件是能被(JavaScript )侦测的行为。
即: 触发— 响应机制。
网页中的每个元素都可以产生某些可以触发 JavaScript 的事件,例如,当用户点击按钮时产生一个事件,然后执行某些操作。
要求:点击按钮弹出警示框,弹出“你好”警示框。
4. 实现步骤:
1).获取事件源;
2)绑定事件,onclick
;
3.)编写事件处理程序,写一个函数弹出 alert 警示框。
5. 实现代码
var btn = document.getElementById('btn');
btn.onclick = function() {
alert('你好吗');
};
1、获取事件源
- 注册事件(绑定事件)
- 添加事件处理程序(采取函数赋值形式)
鼠标事件 | 触发条件 |
---|---|
onclick |
鼠标单击(左键) |
onmouseover |
鼠标经过 |
onmouseout |
鼠标离开 |
onfocus |
获得鼠标焦点 |
onblur |
失去鼠标焦点 |
onmousemove |
鼠标移动 |
onmouseup |
鼠标弹起 |
onmousedown |
鼠标按下 |
JavaScript 的 DOM
操作可以改变网页内容、结构和样式。开发中,可利用 DOM
操作元素来改变元素里面的内容 、属性等。注意以下都是属性:
element.innerText // 从起始位置到终止位置的内容, 但它去除 html 标签, 同时空格和换行也会去掉
element.innerHTML // 起始位置到终止位置的全部内容,包括 html 标签,同时保留空格和换行
innerText、innerHTML 改变元素内容
src、href
id、alt、title
利用 DOM
可以操作如下表单元素的属性:
type、value、checked、selected、disabled
flag
变量,来判断flag
的值,如果是1
就切换为文本框,flag
设置为0
,如果是0
就切换为密码框,flag
设置为1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.box {
position: relative;
width: 400px;
border-bottom: 1px solid #ccc;
margin: 100px auto;
}
.box input {
width: 370px;
height: 30px;
border: 0;
outline: none;
}
.box img {
position: absolute;
top: 2px;
right: 2px;
width: 24px;
}
</style>
</head>
<body>
<div class="box">
<label for="">
<img src="images/close.png" alt="" id="eye">
</label>
<input type="password" name="" id="pwd">
</div>
<script>
// 1. 获取元素
var eye = document.getElementById('eye');
var pwd = document.getElementById('pwd');
// 2. 注册事件
var flag = 0;
eye.onclick = function() {
// 点击之后, flag 的值发生变化
if (flag == 0) {
pwd.type = 'text';
eye.src = 'images/open.png';
flag = 1; // 赋值
} else {
pwd.type = 'password';
eye.src = 'images/close.png';
flag = 0;
}
}
</script>
</body>
</html>
通过 JavaScript 修改元素的大小、颜色、位置等样式。
element.style // 行内样式操作
element.className // 类名样式操作
注:
fontSize
、 backgroundColor
;style
样式的操作,产生的是行内样式,CSS
权重高。class
是保留字,因此使用className
来操作元素类名属性;className
会直接更改、覆盖元素的类名。1)利用样式的显示和隐藏:display:none
隐藏元素 display:block 显示元素;
2)点击按钮,二维码盒子隐藏。
// 1、获取元素
var btn = document.querySelector('.close-btn');
var box = document.querySelector('.box');
// 2.注册事件 程序处理
btn.onclick = function(){
box.style.display = 'none';
}
核心思路:
1)利用for
循环修改精灵图片的背景位置 background-position
;
2)让循环里面的索引号 i
× 44 即为每个li
(图片)的index
(y
坐标)。
实现代码:
var lis = document.querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
var index = i * 44;
lis[i].style.backgroundPosition = '0 -' + index + 'px';
}
**实现效果:**鼠标单击时,默认文字隐藏;当鼠标离开时,文字显示。
实现思路:
1)两个事件:获得焦点 onfocus
失去焦点 onblur
;
2)获得焦点,判断表单里面内容是否为默认文字,如果是,就清空表单内容;
3)如果失去焦点, 判断表单内容是否为空,如果为空,则表单内容改为默认文字。
实现代码:
<body>
<input type="text" value="手机">
<script>
// 1.获取元素
var text = document.querySelector('input');
// 2.注册事件 获得焦点事件
text.onfocus = function() {
if (this.value === '手机') {
this.value = '';
}
// 获得焦点时,文字颜色变深
this.style.color = '#333';
}
// 3. 注册事件 失去焦点事件
text.onblur = function() {
if (this.value === '') {
this.value = '手机';
}
// 失去焦点,文字颜色变浅
this.style.color = '#999';
}
</script>
</body>
onblur
className
修改样式。实现代码:
<body>
<div class="register">
<input type="password" class="ipt">
<p class="message">请输入6~16位密码</p>
</div>
<script>
// 1.获取元素
var ipt = document.querySelector('.ipt');
var message = document.querySelector('.message');
//2. 注册事件 失去焦点
ipt.onblur = function() {
// 根据表单内值的长度 ipt.value.length
if (this.value.length < 6 || this.value.length > 16) {
// console.log('错误');
message.className = 'message wrong';
message.innerHTML = '您输入的位数不对要求6~16位';
} else {
message.className = 'message right';
message.innerHTML = '您输入的正确';
}
}
</script>
</body>
element.属性 // 获取属性值。
element.getAttribute('属性');
区别:
element.属性
:获取内置属性值(元素本身自带的属性);element.getAttribute(‘属性’)
:主要获得自定义的属性(标准) ,程序员自定义的属性element.属性 = '值' // 设置内置属性值。
element.setAttribute('属性', '值');
区别:
element.属性
:设置内置属性值element.setAttribute(‘属性’)
:主要设置自定义的属性 (标准)element.removeAttribute('属性');
getAttribute(‘属性’)
。H5
规定,自定义属性以 data-
开头做为属性名并赋值。
例如:
<div data-index="1"></div> // 或者
// 使用 JavaScript 设置:
element.setAttribute('data-index',2)
element.getAttribute('data-index'); // 兼容性获取;
element.dataset.index // 或者
element.dataset['index'] // H5新增,IE 11才开始支持.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
获取元素通常使用的两种方式:
一、利用DOM提供的方法获取元素 | 二、利用节点层级关系获取元素 |
---|---|
document.getElementById() |
利用父子兄节点关系获取元素 |
document.getElementsByTagName() |
逻辑性强, 但是兼容性稍差 |
document.querySelector 等 |
|
逻辑性不强、繁琐 |
这两种方式都可以获取元素节点,但是节点操作更简单!
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM
中,节点用 node
表示。
HTML
DOM
树中的所有节点均可通过 JavaScript
进行访问,所有 HTML
元素(节点)均可被修改,也可以创建或删除。
一般地,节点至少拥有nodeType
(节点类型)、nodeName
(节点名称)和nodeValue
(节点值)这三个基本属性。
nodeType
为 1nodeType
为 2nodeType
为 3 (文本节点包含文字、空格、换行等)在实际开发中,主要操作的是元素节点。
利用 DOM
树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。
node.parentNode
parentNode
属性可返回某节点的父节点,注意是最近的一个父节点;null
parentNode.childNodes // 标准
parentNode.children // 非标准(各浏览器均支持,可放心使用)
parentNode.firstChild // 返回第一个子节点,找不到则返回null(所有的节点)。
parentNode.lastChild // 返回最后一个子节点,找不到则返回null(所有的节点)
parentNode.firstElementChild // 返回第一个子元素节点,找不到则返回null。
parentNode.lastElementChild // 返回最后一个子元素节点,找不到则返回null
注:
parentNode.childNodes
返回包含指定节点的子节点的集合,该集合是实时更新的。返回值里包含所有的子节点(包括元素节点,文本节点等)。一般不提倡使用childNodes
,如果只想要获得里面的元素节点,需要做如下处理:var ul = document. querySelector('ul');
for(var i = 0; i < ul.childNodes.length;i++) {
if (ul.childNodes[i].nodeType == 1) { // ul.childNodes[i] 是元素节点
console.log(ul.childNodes[i]);
}
}
parentNode.children
是只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回 (重点掌握)。children
虽然是非标准,各浏览器均支持,可放心使用。parentNode.firstElementChild
和 parentNode.lastElementChild
这两个方法有兼容性问题,IE9 以上才支持。实际开发中,firstChild
和 lastChild
包含其他节点,操作不方便,而 firstElementChild
和 lastElementChild
又有兼容性问题,那么该如何去获取第一个子元素节点或最后一个子元素节点?
解决方案:
parentNode.chilren[0]
parentNode.chilren[parentNode.chilren.length - 1]
来获取。1. node.nextSibling
nextSibling
返回当前元素的下一个兄弟元素节点,找不到则返回null
。同样,也是包含所有的节点。
2. node.previousSibling
previousSibling
返回当前元素上一个兄弟元素节点,找不到则返回null
。同样,也是包含所有的节点。
3. node.nextElementSibling
nextElementSibling
返回当前元素下一个兄弟元素节点,找不到则返回null
。
4. node.previousElementSibling
previousElementSibling
返回当前元素上一个兄弟节点,找不到则返回null
。
注意:3、4这两个方法有兼容性问题, IE9 以上才支持。
解决方案:
function getNextElementSibling(element) {
var el = element;
while (el = el.nextSibling) {
if (el.nodeType === 1) {
return el;
}
}
return null;
}
document.createElement('tagName')
document.createElement
() 方法创建由 tagName
指定的 HTML 元素。这些元素根据我们的需求动态生成,所以也称为动态创建元素节点
。
1. node.appendChild(child)
node.appendChild
() 方法将一个节点添加到指定父节点的子节点列表末尾。类似于 CSS 里面的 after 伪元素。
2. node.insertBefore(child,指定元素)
node.insertBefore
() 方法将一个节点添加到父节点的指定子节点前面。类似于 CSS 里面的 before 伪元素
li
添加到ul
里面。li
的同时,把文本域里面的值通过li.innerHTML
赋值给 li
appendChild
;反之,如果想要始终在前面显示,就用insertBefore
。<body>
<textarea name="" id=""></textarea>
<button>发布</button>
<ul>
</ul>
<script>
// 1. 获取元素
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
// 2. 注册事件
btn.onclick = function() {
if (text.value == '') {
alert('您没有输入内容');
return false;
} else {
// console.log(text.value);
// (1) 创建元素
var li = document.createElement('li');
// 先有li 才能赋值
li.innerHTML = text.value;
// (2) 添加元素
// ul.appendChild(li);
ul.insertBefore(li, ul.children[0]);
}
}
</script>
</body>
node.removeChild(child)
node.removeChild
() 方法从 DOM 中删除一个子节点,返回删除的节点。
结合上面的留言发布案例,做为本节的删除案例予以实现
案例:删除留言案例
li
时,同时添加一个删除的链接(a
标签);li
;#
,故需阻止链接跳转,相应的就要添加 javascript:void(0);
或者 javascript:;
(推荐后者,在使用上更简单方便)。案例分析:
1)由于学生数据是动态的,因此需要用JavaScript 动态生成。 这里采用模拟数据,采取对象形式存储;
2)所有的数据都放到tbody
里面的行里面;
3)因为行比较多,需要循环创建多行(对应人数);
4)每行面又有很多单元格(对应里面的数据),还需继续使用循环创建多个单元格,并且把数据存入里面(双重for循环);
5)最后一列单元格是删除
,需要单独创建单元格;
6)添加删除程序,单击删除,可以删除当前行。
实现代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
table {
width: 500px;
margin: 100px auto;
border-collapse: collapse;
text-align: center;
}
td,
th {
border: 1px solid #333;
}
thead tr {
height: 40px;
background-color: #ccc;
}
</style>
</head>
<body>
<table cellspacing="0">
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
// 1.准备数据(在数组中创建模拟数据替代数据库)
var datas = [{
name: '周润发',
subject: '影视表演',
score: 99
}, {
name: '李小龙',
subject: '影视表演',
score: 99
}, {
name: '刘德华',
subject: '流行歌曲',
score: 95
}, {
name: '马云',
subject: '商业运营',
score: 95
}, {
name: '刘强东',
subject: '商业运营',
score: 90
}];
// 2. 在tbody 内创建行: 通过数组长度取得人数,从而得到动态的要创建的行数。
var tbody = document.querySelector('tbody');
for (var i = 0; i < datas.length; i++) { // 外层for循环决定行数,即tr
// 1. 创建 tr行
var tr = document.createElement('tr');
tbody.appendChild(tr);
// 2. 行内创建单元格(跟数据有关的单元格) td;
// 单元格的数量取决于每个对象里属性的个数,for循环遍历对象 datas[i]
for (var k in datas[i]) { // 内层for循环决定列td
// k 得到属性名
// object[k] 得到属性值
// 创建单元格
var td = document.createElement('td');
// 把对象的属性值 datas[i][k] 赋给td
td.innerHTML = datas[i][k];
tr.appendChild(td);
}
// 3. 创建存放“删除”a标签的单元格
var td = document.createElement('td');
td.innerHTML = ' 删除 ';
tr.appendChild(td);
}
// 4. 删除
var as = document.querySelectorAll('a');
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
// 语法:node.removeChild(child)
// 单击a标签 删除当前 a 所在的行(a链接的父级的父级)
tbody.removeChild(this.parentNode.parentNode)
}
}
</script>
</body>
</html>
node.cloneNode()
node.cloneNode
() 方法返回调用该方法的节点的一个副本。 也称为克隆节点/拷贝节点
注:
false
,则是浅拷贝(只克隆复制节点本身,不克隆里面的子节点)。true
,则是深度拷贝(会复制节点本身以及里面所有的子节点)。document.write
()element.innerHTML
document.createElement
()方法 | 特点 |
---|---|
document.write () |
是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘 |
innerHTML |
是将内容写入某个 DOM 节点,不会导致页面全部重绘。 |
创建多个元素效率更高(数组形式拼接,不要拼接字符串),结构稍微复杂 | |
createElement () |
创建多个元素时,比innerHTML 数组法的效率稍低一点点,但结构更清晰。 |
备注:不同浏览器下,innerHTML
效率比 creatElement
要高。
序号 | 创建 | 增 | 删 | 改 | 查 | 属性操作 |
---|---|---|---|---|---|---|
1 | document.write | appendChild | removeChild | 修改元素属性: src、href、title等 | DOM提供的API 方法: getElementById、getElementsByTagName (不推荐) | setAttribute:设置dom的属性值 |
2 | innerHTML | nsertBefore | 修改普通元素内容: innerHTML 、innerText | H5提供的新方法: querySelector、querySelectorAll 提倡 | getAttribute:得到dom的属性值 | |
3 | createElement | 修改表单元素: value、type、disabled等 | 利用节点操作获取元素: 父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling) 提倡 | removeAttribute移除属性 | ||
4 | 修改元素样式: style、className |
鼠标事件 | 触发条件 |
---|---|
onclick |
鼠标单击(左键) |
onmouseover |
鼠标经过 |
onmouseout |
鼠标离开 |
onfocus |
获得鼠标焦点 |
onblur |
失去鼠标焦点 |
onmousemove |
鼠标移动 |
onmouseup |
鼠标弹起 |
onmousedown |
鼠标按下 |