DOM
# DOM
DOM(document object model):将标记语言文档的各个组成部分,封装为对象。可以使用这些对象,对标记语言文档进行 CRUD 的动态操作
W3C DOM 标准被分为 3 个不同的部分:
- 核心 DOM - 针对任何结构化文档的标准模型
- Node:原生节点对象,以下节点对象都继承于此
- Document:文档对象,整个文档树的顶层节点
- DocumentType:
doctype标签(比如<!DOCTYPE html> - Element:元素对象,网页的各种 HTML 标签(比如
<body>、<a>等) - Attribute:属性对象,网页元素的属性(比如
class="right") - Text:文本对象,标签之间或标签包含的文本
- Comment:注释对象
- DocumentFragment:文档的片段
- XML DOM - 针对 XML 文档的标准模型
- HTML DOM - 针对 HTML 文档的标准模型
解析过程:根据 html 的层级结构,在内存中分配一个树形结构,需要把 html 中的每部分封装成对象
# Node 🔥
节点对象,其他对象的父对象。所有 dom 对象都可以被认为是一个节点
JS 中有宿主对象 document(文档对象本身),是 window 对象的属性。DOM 中的对象又称为节点对象,4 种常用节点:
| nodeName | nodeType | nodeValue | |
|---|---|---|---|
| Document 文档节点 | #document | 9 | null |
| Element 元素节点 | 标签名 | 1 | null |
| Attribute 属性节点 | 属性名 | 2 | 属性值 |
| Text 文本节点 | #text | 3 | 文本内容 |
# Node 接口 🔥
属性:
nodeType:一个整数值表示==节点的类型==。如 Element 为 1、Attribute 为 2、Text 为 3、Document 为 9nodeName:节点的名称。如 Element 为大写标签名、Attribute 为属性名、Text 为#text、Document 为#documentnodeValue:一个字符串,表示当前节点本身的文本值。只有 Attribute、Text、Comment 有值,其余返回nulltextContent:当前节点和它的所有后代节点的==所有文本内容==,自动忽略当前节点内部的 HTML 标签baseURI:一个字符串,表示当前网页的绝对路径ownerDocument:当前节点所在的顶层文档对象,document 本身的这个属性为null。与getRootNode()一样作用previousSiblin:当前节点==前==面的、距离最近的一个同级节点,没有同级节点则返回nullnextSibling:紧跟在当前节点==后==面的第一个同级节点,没有同级节点则返回nullparentNode:==当前节点的父节点==,可能有三种类型,如 Document、Element、DocumentFragmentparentElement:当前节点的父元素节点,排除了上述类型中首尾两个
方法(CRUD DOM 树):
appendChild(newNode):==将其作为最后一个子节点,插入当前节点==。若newNode为 DOM 中已存在的,相当于剪贴insertBefore(newNode,oldNode):节点之前插入一个新的节点,没有 insertAfter()方法可以结合nextSibling实现removeChild(Node):通过父节点删除指定子节点,并返回被删除的节点。不存在 DOM 中,但在内存中仍可使用replaceChild(newNode,oldNode):通过父节点用新节点替换一个子节点cloneNode(boolean b):复制节点返回新节点,boolean 表示是否复制子节点,会丧失该节点上的事件回调函数childNodes:当前节点的所有子节点的NodeList集合,但是包括 Text、Commnet!空格之类的都包括!别用!hasChildNodes():当前节点是否有子节点,也是包括所有类型节点!空格也算!别用!
# NodeList 接口(了解)
NodeList实例是一个类似数组不是数组的对象,它的成员是节点对象。通过以下方法可以得到NodeList实例Node.childNodes:说了别用!省的没注意空格!document.querySelectorAll()等节点搜索方法
- 属性:
length,NodeList 实例包含的节点数量
- 方法:
forEach,也可以使用 for 循环。没 pop、pust 等方法哦!item(index):接受一个整数值作为参数,表示成员的位置,返回该位置上的成员。
- 。。。懒得看了
# HTMLCollection 接口(了解)
HTMLCollection是一个节点对象的集合,只能包含元素节点(element),不能包含其他类型的节点。它的返回值是一个类似数组的对象,但是与NodeList接口不同,HTMLCollection没有forEach方法,只能使用for循环遍历- 返回
HTMLCollection实例的,主要是一些Document对象的集合属性,比如document.links、docuement.forms、document.images、document.styleSheets、document.scripts等 HTMLCollection实例都是动态集合,节点的变化会实时反映在集合中- 属性
length:返回HTMLCollection实例包含的成员数量
- 方法
item():接受一个整数值作为参数,表示成员的位置,返回该位置上的成员namedItem():参数是一个字符串,表示id属性或name属性的值,返回对应的元素节点。如果没有则返回null
# ParentNode 接口(注意 IE 基本不支持)
- 只有元素节点(element)、文档节点(document)和文档片段节点(documentFragment)拥有子节点,因此只有这三类节点会继承
ParentNode接口 - 属性
children:返回一个HTMLCollection实例,成员是当前节点的所有元素子节点。该属性只读。firstElementChild:当前节点的第一个元素子节点。如果没有任何元素子节点,则返回nulllastElementChild:当前节点的最后一个元素子节点,如果不存在任何元素子节点,则返回nullchildElementCount:返回一个整数表示当前节点的所有元素子节点的数目。如果不包含任何元素子节点则返回0
- ==方法(如下方法都没有返回值)==
append():为当前节点的最后一个元素子节点后追加一个或多个子节点。可以添加元素子节点、文本子节点。IE 全不支持!!!prepend():为当前节点的的第一个元素子节点前追加一个或多个子节点。同 append()方法- 若是若
newNode为 DOM 中已存在的,相当于剪贴
- 若是若
# ChildNode 接口
- 如果一个节点有父节点,那么该节点就继承了
ChildNode接口 - ==方法(都是本节点调用方法)==
remove():==用于从父节点移除当前节点,自己调用删除自己!因为已知本节点有父节点==before():当前节点的前面,插入一个或多个同级节点,两者拥有相同的父节点。可以插入元素节点、文本节点after():在当前节点的后面,插入一个或多个同级节点,两者拥有相同的父节点。同 before()方法replaceWith():使用参数节点,替换当前节点。参数可以是元素节点,也可以是文本节点
# Document 🔥
# 简介
在 HTML DOM 模型中有宿主对象document,它是window对象的属性(也可以省略)。
继承了 Node、ParentNode 等接口
# 常用属性(好像不太常用)
body该属性封装的是 body 元素对象的引用
documentElement属性值为 HTML 元素对象
all属性值为当前页面中的所有元素节点的数组。这个属性值本身为
undefined,它的typeof值也为undefinedURL获取当前页面的 url
domain获取当前页面的域名部分
referrer获取是哪个页面链接跳转到当前页面,没有则返回空字符串
# 常用 CRUD 方法 🔥
# 获取 Element 对象
注意
可以使用Document对象和Element对象调用如下函数。但是~ById()函数只能用在Document对象上
注意
如下方法都支持 IE8 及以上
querySelector():CSS 选择器为参数,如果有多个节点满足匹配条件,则返回第一个匹配的节点,没有则返回 nullquerySelectorAll():返回一个NodeList对象,包含所有匹配给定选择器的节点。用法同上【注意】不支持 CSS 伪元素选择器和伪类选择器
getElementById("id"):根据 ID 属性获取一个元素对象,效率比querySelector()高getElementsByClassName("className"):标签的 class 的属性值得到元素集合(HTMLCollection实例)getElementsByTagName("tagName"):标签名称得到元素集合(HTMLCollection实例)getElementsByName("name"):标签的 name 属性值得到元素集合(NodeList实例),radio、checkBox 等只有一个标签时通过
document.getElementsByTag/ClassName("input")[0]获取元素对象获取标签下面的子孙标签的唯一有效办法,使用父节点**
getElementsByTagName()**方法,不使用 childNodes 属性
# 添加 DOM 对象
createElement("元素名称"):创建元素节点,参数为 tagName 属性,对 HTML 不区分大小写,但不能加尖括号createTextNode("文本内容"):创建文本节点,可以在内容中添加标签。不能对属性赋值,不会转义单双引createAttribute(name):创建拥有指定名称的属性节点,并返回新的 Attr 对象。通过 Node 来设置属性createComment():创建注释节点
# 其他
- write():向页面输出变量(值)、html 代码
# Element 🔥
通过document来获取和创建
# 常用属性
innerHTML:返回一个字符串,等同于该元素包含的所有 HTML 代码,该属性可读写。用来设置某个节点的内容innerText:同上,但是只显示文本代码,不带标签的!!,设置内容也不会解析为 HTMLtextContent:显示文本或插入的是文本时使用来替代上面方法。原样显示,不像上面方法会转为&**;来显示value:代表的是元素的 value 属性,一般用于**input标签值的获取**,**select**标签值也可以使用style:用来读写该元素的行内样式信息,配合 CSS。如 display 可取值 none、block、inner也可以提前定义好类选择器的样式,通过元素的
className属性来设置其class属性值。
# 常用 Attribute 方法
getAttribute("name"):获取属性里面的值setAttribute("name","value"):设置属性的值removeAttribute("name"):删除属性,不能删除 value 属性
# Event
# 加载事件
onload文档被浏览器加载时触发,只能写一次;一般在 body 标签中注册函数;或用 window 来调用。此时可以操作 DOM 元素**。
window.onload = function() { document.getElementById('btn').onclick = function() { alert('haha') } }1
2
3
4
5
# 点击事件
onclick:点击事件(按钮)ondblclick:双击事件
# 焦点事件(表单校验)
onfocus:组件获得焦点事件(输入框/单选/多选/下拉) ,光标闪动onblur:组件失去焦点事件(输入框/单选/多选/下拉)
# 改变事件
onchange:域的内容改变/选择的值发生变化事件(输入框/下拉)onselect:文本被选中
# 表单事件
onsubmit:表单提交按钮按下时触发的事件(表单校验)在 form 后注册函数,有返回值 true/false,控制提交与否必须写
return 函数名否则不能获取到返回的 boolean 值onreset:重置按钮按下时
# 鼠标事件
onmouseover():鼠标移动到组件上时触发onmouseout:鼠标移出组件时触发onmousemove:鼠标移动就触发onmousedown:鼠标按键按下时触发定义方法时,定义一个形参来接收
event对象,它的button属性可以获取鼠标哪个按钮被点击(0,1,2)onmouseup:鼠标按键松开时触发
# 键盘事件
onkeydown:某个键盘按键被按下onkeyup:某个键盘按键被松开onkeypress:某个键盘按键被按下并松开
# 案例
# 动态显示时间
let ele = document.getElementById('h1')
function setTime() {
let s = new Date().toLocaleString()
ele.innerText = s
}
setInterval(setTime, 1000)
2
3
4
5
6
# 轮播图(正常不这么做)
var i = 1
function changeImg() {
i++
if (i > 3) i = 1
document.getElementById('img1').src = 'img/' + i + '.jpg'
}
setInterval(changeImg, 5000)
2
3
4
5
6
7
# 定时弹出广告(style.display)
showTime = setTimeout(showAd, 3000) //定义为全局变量
function showAd() {
document.getElementById('adImg').style.display = 'block'
clearTimeout(showTime)
hiddenTime = setTimeout(hiddenAd, 3000)
}
function hiddenAd() {
document.getElementById('adImg').style.display = 'none'
clearTimeout(hiddenTime)
}
2
3
4
5
6
7
8
9
10
11
12
# 动态增删表格
document.getElementById('btn').onclick = function() {
let id = document.getElementById('id').value
let name = document.getElementById('name').value
let sex = document.getElementById('sex').value
//thead
let tbd = document.getElementsByTagName('thead')[0]
document.getElementById('btn').onclick = function() {
let id = document.getElementById('id').value
let name = document.getElementById('name').value
let sex = document.getElementById('sex').value
let thd = document.getElementsByTagName('thead')[0]
thd.innerHTML +=
'<tr>\n' +
' <td>' +
id +
'</td>\n' +
' <td>' +
name +
'</td>\n' +
' <td>' +
sex +
'</td>\n' +
' <td><a href="javascript:void(0);" onclick="delTr(this);" >删除</a></td>\n' +
' </tr>'
//使用方法一个个添加也行,但是麻烦
}
function delTr(obj) {
var parentNode = obj.parentNode.parentNode.parentNode
var deleteNode = obj.parentNode.parentNode
parentNode.removeChild(deleteNode)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 全选/全不选/反选/高亮
let inputs = document.getElementsByClassName('check-box')
//全选
document.getElementById('selectAll').onclick = function() {
for (let i in inputs) {
inputs[i].checked = true
}
}
//全不选
document.getElementById('notSelect').onclick = function() {
for (let i in inputs) {
inputs[i].checked = false
}
}
//反选
document.getElementById('reverseSelect').onclick = function() {
for (let i in inputs) {
inputs[i].checked = !inputs[i].checked
}
}
//左上角选择
document.getElementById('ck1').onclick = function() {
for (let i in inputs) {
inputs[i].checked = this.checked
}
}
//表格行高亮
let trs = document.getElementsByTagName('tr')
for (let t in trs) {
trs[t].onmouseover = function() {
this.style.backgroundColor = 'gray'
}
trs[t].onmouseout = function() {
this.style.backgroundColor = 'white'
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 表单校验
window.onload = function () {
//表单校验
document.getElementById("form").onsubmit = function () {
return checkUsername();//可添加密码校验
}
document.getElementById("username").onblur = checkUsername;//可添加密码校验
}
//用户名校验
function checkUsername() {
var username = document.getElementById("username").value;
var reg = /^\w{6,12}$/;
let flag = reg.test(username);
if (flag) {
document.getElementById("usernameSpan").innerHTML = "✔";
} else {
document.getElementById("usernameSpan").innerHTML = "用户名格式有误";
}
return flag;
}
//可添加密码校验等等
。。。。。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 左右列表
- select、option、multiple、selected=true/false、appendChild()剪贴的 length 变化
var left = document.getElementById('left')
var leftlist = left.getElementsByTagName('option')
var right = document.getElementById('right')
var rightlist = right.getElementsByTagName('option')
var toRight = function() {
for (let i = 0; i < leftlist.length; i++) {
if (leftlist[i].selected) {
right.appendChild(leftlist[i])
i--
}
}
}
var allToRight = function() {
for (let i = 0; i < leftlist.length; i++) {
right.appendChild(leftlist[i])
i--
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 表格隔行换色(tBodies、rows)
//这样也可以获得行数
//var tbody = document.getElementsByTagName("tbody")[0];
//var rows = tbody.getElementsByTagName("tr").length;
var tb = document.getElementById('table1')
var rows = tb.tBodies[0].rows.length
for (let i = 0; i < rows; i++) {
if (i % 2 === 0) {
tb.tBodies[0].rows[i].style.backgroundColor = 'gray'
} else {
tb.tBodies[0].rows[i].style.backgroundColor = 'yellow'
}
}
2
3
4
5
6
7
8
9
10
11
12
13
# 省市联动(this.value)
let arr = [
['陕西', '西安', '商洛', '延安', '安康'],
['河北', '石家庄', '廊坊', '秦皇岛', '雄安'],
['广东', '深圳', '珠海', '广州', '不知道'],
]
document.getElementById('sheng').onchange = function() {
let option = document.getElementById('shi') //不能直接使用innerHTML来赋值
option.innerHTML = '' //每次改变时要清空
for (let i in arr) {
if (arr[i][0] === this.value) {
for (let j = 1; j < arr[i].length; j++) {
option.innerHTML += '<option>' + arr[i][j] + '</option>'
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17