module3-02-DOM
一、DOM的概念
-
文档对象模型,是W3C组织推荐的处理可扩展标记语言的标准变成接口。它是一种与平台和语言无关
-
内部封装了一整套操作HTML的接口
-
1.1 DOM 树
-
DOM又称为文档数模型
-
文档:一个网页可以称为文档
-
节点:网页中的所有内容都是节点(标签、属性、文本、注释)
-
元素:网页中的标签
-
属性:标签的属性
-
1.2 DOM经常进行的操作
-
获取元素
-
对元素进行操作(设置其属性或调用方法)
-
动态创建元素
-
事件(什么时机做相应的操作)
二、获取DOM元素的方法
-
为什么要获取页面元素
-
要先获取页面上的元素,才可以对其进行显示/隐藏或增加动画,需要先获取到该部分对应的元素才进行后续的操作
2.1 根据id获取元素
-
调用document对象的getElemenetById
-
参数:字符串类型的id属性值(区分大小写)
-
返回值:对应id名的元素对象
-
如果有多个同id的元素,则返回第一个
-
-
检测:
-
使用tyoeof返回object
-
使用console.dir()
-
注意事项
-
由于id名具有唯一性,部分浏览器支持直接使用id名访问元素,但不是标准方式,不推荐使用
-
下面这个的para就没有使用document方法获取
-
如果有多个同名的id那么下面的para代表的是一个伪数组
-
para.style.bakcground = 'pink // 属性值记得用字符串形式
para[1].style.background = 'green' // 表示id为para的第二个元素的背景色改成green
-
对代码书写顺序有要求(静态获取),须保证元素已经在浏览器中渲染成功
-
需要将js代码写在html元素之后(不可以动态添加)
-
2.2 根据标签名获取元素
-
方法:调用document对象的getElementsByTagName方法
-
没有getElementByTagName
-
-
参数:字符串类型的标签名
-
返回值:同名的元素对象组成的数组(伪数组)
注意事项
-
① 操作数据时需要按照操作数组的方法进行
-
② getElementsByTagName方法内部获取的元素是动态增加
-
即可以在html结构前就对元素进行获取
-
2.3 元素对象内部获取元素
-
获取的元素对象内部,本身也可以调用根据标签获取元素方法,例如div元素对象也可以调用getElementsByTagName方法
-
类似css的子级选择器
-
-
目的:缩小选择元素的范围,类似css中的后代选择器
var box1 = document.getElementsById('box1').getElementsByTagName('p')
// 平时习惯会先保存box1然后再用box1获取其内部的p
2.4 根据name获取元素
-
方法:调用document对象的getElementsByName方法
-
参数:字符串类型的name属性值
-
返回值:name属性值相同的的元素对象组成的数组,属于NodeList节点集合,而之前的是属于HTMLCollection
注意事项
-
兼容问题:在IE和Opera中有兼容问题,会多选中id属性值相同的元素,所以不推荐
-
可以动态添加
2.5 根据类名获取元素
-
方法:调用document对象的getElementsByClassName方法
-
参数:字符串类型的class属性
-
返回值:class属性值相同的元素对象组成的HTMLCollection数组
注意事项
-
不支持IE8及以下浏览器
-
可以动态添加
-
元素对象中也可以调用getElementsByClassName
2.6 根据选择器获取元素
-
① 调用document对象的querySelector方法,通过css中的选择器去选取第一个符合条件的标签元素
-
② 调用document对象的querySelectorAll方法,通过css中的选择器去选取所有符合条件的标签元素
-
参数:字符串类型的css中的选择器
-
返回值:用all的话就会返回一个NodeList集合
注意事项
-
需要在HTML结构加载完之后调用
-
不支持IE8以下的浏览器
2.7 总结
掌握,没有兼容问题
-
getElementById()
-
getElementsByTagName()
了解
-
getElementsByName()
-
getElementsByClassName()
-
下面两个在没有兼容问题的时候推荐使用
-
querySelector()
-
querySelectorAll()
三、DOM事件基本应用
3.1 事件的基本概念
-
事件:在什么时候做什么事
-
执行机制:触发--响应机制
-
绑定事件(注册事件)三要素:
-
事件源:给谁绑定事件
-
事件类型:绑定什么类型的事件click单机
-
事件函数:事件发生后执行什么内容,写在函数内部
-
事件监听
-
JavaScript解析器会给所有绑定事件的元素添加一个监听,解析器会一直检测这个元素,只要触发对应的绑定事件,会立刻执行时间函数
常用的鼠标事件类型
-
onclick 鼠标左键单击触发
-
ondbclick 鼠标左键双击触发
-
onmousedown 鼠标按键按下触发
-
onmouseup 鼠标按键放开时触发
-
onmousemove 鼠标在元素上移动触发
-
onmouseover 鼠标移动到元素上触发
-
onmouseout 鼠标移出元素触发
3.2 非表单元素属性操作
-
例如:href、title、id、src
-
路径会自动转换为绝对路径呈现
-
-
调用方式:元素对象打点调用属性名,例如obj.href
-
属性赋值:给元素属性赋值,等号右侧的赋值都是字符串格式
注意事项
-
id一般都是用作只读
-
但也可以更改(不推荐)
-
-
注意:部分的属性名跟关键字和保留字冲突,会更换写法
-
class -> className
-
for -> htmlFor
-
rowspan -> rowSpan
-
案例
-
点击按钮切换图片
-
不可以把.src的属性作为判读按条件,因为获取到的是绝对路径并非相对路径
-
可以使用一个变量来表示当前的状态
-
3.3 事件函数内部的this
-
事件函数中的内部有一个this,指向事件源
-
区分一下不同函数内部this的指向
-
普通函数 -> window对象
-
构造函数 -> 生成实例的对象
-
对象的方法 -> 对象本身
-
事件函数 -> 事件源
-
案例
-
美女画廊(点击图片可以让一个盒子的图片切换显示)
-
取消a的默认行为,在其点击函数中
return false
,或者e.preventDefault()
-
在for循环给a设置点击事件的时候
-
3.4 获取标签内部内容
-
获取标签内部内容的属性有两个:innerHTML、innerText
-
innerHTML:
-
如果标签内部包含标签,则获取到的内容也会包含标签(包括空白换行)
-
-
innerText:
-
如果包含标签,则获取到的内容会过滤标签(去掉换行和缩进等空白)
-
更改标签内容
-
innerHTML:里面的内容会根据HTML语法的标签加载
-
适用场景:内部有子标签结构
-
-
-
innerText:里面的内容会按照普通的字符串加载
-
适用场景:设置纯字符串
-
-
3.5 表单元素属性
-
value:用于大部分表单元素的内容获取(option除外)
-
type:可以获取input标签的类型(输入框或复选框)
-
disable:禁用属性
-
checked:复选框选中属性
-
selected:下拉菜单选中属性
-
注意在DOM中元素对象的属性只有一个(且只有同名的时候)时,会被转换成布尔值显示
-
如
disabled = true
不建议写成disabled = 'disabled'
-
注意事项
-
表单元素是value来获取的
-
非表单元素是innerHTML或innerText获取的
-
双标签的表单元素也是如:option
-
表单元素的案例
-
检测输入内容
-
设置下拉框的选中项
-
搜索文本框
-
全选反选
四、其它的一些DOM操作
4.1 自定义属性操作
-
getAttribute(name) 获取标签行内属性
-
setAttribute(name, value) 设置标签行内属性
-
removeAttribute(name) 移除标签行内属性
-
与element.属性的区别:上述三个方法用于获取任意的行内属性,包括自定义的属性
注意事项
-
用setAttribute的时候传的参数不需要进行更改,如:传入class即可。因为传入的是字符串
4.2 style样式属性操作
-
使用style属性方法设置的样式显示在标签行内
-
element.style 属性的值,是所有行内样式组成的一个样式对象(CSSStyleDeclaration)
-
样式对象可以继续用点语法调用或更改css的行内样式属性,例如width、height等属性
注意事项
-
background-color在js的写法要写成驼峰法如backgroundColor
-
通过样式熟悉感设置宽高、位置的属性类型是字符串,要加上px等单位
-
点style只能获取行内样式的东西,不能获取因为类名而赋予的属性
修改样式的方法选择
-
className类名属性操作
-
修改元素的className属性相当于直接修改标签的类名
-
如果需要修改多条css样式,可以提前将修改后的样式设置到一个类选择器中,后续通过修改类名的方式,批量修改css样式
-
-
element.style方式修改
综合案例
(1)开关灯
-
可以利用元素自身的属性来判断当前的状态
(2)显示隐藏二维码
-
使用js修改className的时候切记这个方法是否会重置之前的类名
-
可以使用replace
-
(3)排他思想-文本框高亮显示
-
先用for排除所有,然后循环后单独为自己添加样式
(4)设置元素怒的大小和位置案例
-
使用className设置样式
-
在js中使用element.style方法设置样式,注意加单位
(5)表格隔行变色和高亮显示
-
在定义事件函数的作用域中,添加一个变量来记录原本的颜色,然后给onmouseout事件中使用其来回复原来的颜色
(6)tab选项卡切换
-
排他思想
-
对应控制思想:有两组数据中存储了相同个数的元素对象,一组对象的变化,会引起另外一组的变化
-
可以在变化的元素加上自定义属性
.index = i
,则在该元素的事件触发函数中,使用this.index即可获取相应的下标
-
五、DOM节点操作
5.1 节点属性
-
nodeType:节点属性,属性值为数字,表示不同的节点类型,共12种,且只读
-
① 元素节点
-
nodeValue为null
-
-
② 属性节点
-
可以通过getAttributeNode()来获取
-
nodeName为属性名
-
nodeValue为其值
-
如设置了
style="width: 100px; height: 100px;"
则getAttributeNode('style').nodeValue就是width: 100px; height: 100px;
-
-
-
③ 文本节点
-
可以通过childNodes来获取
-
其nodeName为#text
-
其nodeValue为其文本值
-
-
-
nodeName:节点的名称(如果是元素则是标签名),只读
-
nodeValue:节点值,返回或设置当前节点的值,元素节点的nodeValue始终是null
5.2 父子节点常用属性
-
childNodes:只读属性,获取一个节点素有子节点的实时的集合,集合是动态变化的。
-
children:只读属性,获取一个节点所有的子元素节点集合,是一个动态更新的HTML元素集合
-
firstChild:只读属性,返回该节点的第一个子节点,如果该节点没有子节点则返回null
-
lastChild:只读属性,返回该节点的最后一个子节点,如果该节点没有子节点则返回nukk
-
可以使用firstElementChild或者lastElementChild来获取元素节点而不是所有节点
-
-
parentNode:返回一个当前节点的父节点,如果没有这样的节点,比如说这个节点是书结构的顶端或者没有插入一棵树种,这个属性返回null
-
比如createElement新创建的节点或者document节点
-
-
parentElement:返回当前节点的父元素节点,如果该元素没有父节点,或者父节点不是一个DOM元素,则返回null
5.3 兄弟节点常用属性
-
nextSibling:只读属性,返回与该节点同级的下一个节点
-
previousSibling:只读属性,返回与该节点同级的上一个节点
-
nextElementSibling:只读属性,返回与该节点同级的下一个元素节点
-
previousElementSibling:只读属性,返回与该节点同级的上一个元素节点
注意事项
-
nextElementSibling与previousElemtnSibling有兼容性问题,在IE9以后才支持
5.4 创建与添加新节点的方法
(1)创建方法
-
document.createElement('div'):创建元素节点
-
document.createAttribute('id'):创建属性节点
-
document.createTextNode('hello'):创建文本节点
-
一般将创建的新节点存在变量中,方便使用
(2)添加方法
-
parentNode.appendChild(child):将一个节点添加到父节点的子节点列表末尾
-
parentNode.replaceChild(newChild, oldChild):用指定的节点替换当前节点的一个子节点,并返回被替换掉的节点
-
parentNode.insertBefore(newNode, referenceNode):在参考节点之前插入一个拥有指定父节点,referenceNode必须设置,如果referenceElement为null则newNode将被插入到子节点的末尾
-
parentNode.removeChild(child):移除当前节点的一个子节点,这个子节点必须存在于当前节点中
-
注意事项
-
将原有节点用于此操作的话,会先移除在当前DOM的位置,再进行添加到DOM树指定位置,即剪切
-
5.5 克隆节点
-
Node.cloneNode():克隆一个节点,并且可以选择是否克隆这个节点下的所有内容
-
参数为true:克隆所有后代节点
-
参数为false:只克隆本身节点
-
-
注意事项
-
标签上的属性和属性值也会被克隆,行内绑定的事件可以被复制,js动态绑定的事件不会被复制
-
5.6 判断是否有后代节点
-
Node.hasChildNodes():没有参数,返回一个Boolean值,来表示是否含有
-
Node.contains(child):返回一个Boolean(),来表示是否为该节点的后代
-
不一定是父子关系,包含即返回true
-
其它判断的方法
-
node.firstChild !== null
-
node.childNodes.length > 0
-
可以用children来判断是否含有元素子节点
-
-
node.hasChildNodes()
六、DOM一些特效制作
-
在制作这些之前,先认识一些常用的属性
6.1 偏移量属性offset系列属性
-
offsetParent:偏移参考父级,距离子级最近的有定位的父级,如果没有定位参考body(html)
-
offsetLeft / offsetTop:偏移位置
-
可以是margin撑开的高度宽度
-
-
offsetWidth / offsetHeight:偏移大小
-
boder+padding+content
-
6.2 客户端大小client系列属性
-
client系列没有参考父级元素
-
clientLeft / clientTop:边框区域(border大小),不常用
-
clientWidth / clientHeight:边框内部大小,不算border的大小
6.3 滚动偏移属性scroll属性
-
scrollLeft / scrollTop 盒子内部滚动出去的尺寸
-
scrollWidth / scrollHeight 盒子内容的宽度和高度,包含不可见部分
6.4 一些案例
(1)拖拽案例
-
确认鼠标在该元素中的位置
-
然后给onmouseup中加入onmousemove事件
drop.onmousedown = function (e) {
e = e || window.event
// console.log (e.pageX + '-' + box.offsetLeft)
var l = e.pageX - box.offsetLeft
var t = e.pageY - box.offsetTop
console.log(l, t)
box.onmousemove = function (e) {
this.style.top = e.pageY - t + 'px'
this.style.left = e.pageX - l + 'px'
}
}
drop.onmouseup = function (e) {
box.onmousemove = null
}
(2)弹出层
-
弹出一个遮罩层,让其它元素不能点击,使用z-index和透明度属性
-