下属于Part2 Module3:Web APIs 网页应用编程
Step1:DOM 概念
Step1:DOM 获取页面元素
根据 id 获取元素#3
方法:document.getElementById()
参数:字符串类型的 id 的属性值
返回值:对应 id 名的元素对象
var para =
补充:在控制台打印具体的对象
console.dir();
注意:
- 注意代码的执行顺序,js 放在 HTML 后面。如果 js 在 html 结构之前,会导致结构未加载,不能获取对应 id 的元素。
- js 中的 id 唯一性。如果有多个同 id 元素,js 只会选中第一个找到的元素。
- 部分浏览器支持直接使用 id 名访问元素,但不是标准方式,不推荐使用
根据 元素名 获取元素#4
方法:document.getElementsByTagName()
参数:字符串类型的标签名
返回值:同名的元素对象组成的(伪)数组,HTMLcollection
注意:
-
操作方法与操作数组的方法一致
-
此方法内部获取的元素是动态增加的。可以放在 HTML 结构前。
-
获取元素的顺序是依照 HTML 中元素的开始标签的先后顺序。
元素对象内部获取元素#5
连续调用方法,进一步选中元素对象。
类似于 CSS 的后代选择器:
#box p {
}
选中 id 为 box 元素下的 p 元素。
在js中:
var bs = document.getElementById('box').getElementsByTagName('p');
通常来说,将连续调用拆分开写,分别定义变量赋值,更有利于后续使用:
var box = document.getElementById('box');
var ps = box.getElementsByTagName('p');
根据 name 属性获取元素#6
方法:document.getElementsByName()
参数:字符串类型的 name 属性值。
返回值:name 属性值相同的元素对象组成的数组
兼容性:IE 9 和 Opera 下有兼容性问题
注意:
-
动态增加。和 getElementsByTagName() 相同
-
获取到的是 NodeList,而非 HTMLcollection
根据 类名 获取元素#7
方法:document.getElementsByClassName()
参数:字符串类型的 class 属性值
返回值:class 属性值相同的元素对象组成的数组,HTMLcollection
兼容性:不支持 IE 8 及以下
注意:
- 动态增加
根据 选择器 获取元素#8
方法:document.querySelector()
参数:字符串类型的 css 中的选择器
兼容:不支持 IE 8 及以下
注意:
- 需要在 HTML 后面使用
- 只能获取第一个符合选中条件的元素。另有 document.querySelectorAll() 可以获取到所有符合条件的元素,返回 NodeList
Step2:DOM 事件基本应用
事件#9
执行机制:触发 → 响应
绑定事件(注册事件)三要素:
事件源(绑定对象)
事件类型(如何触发)
事件函数(如何响应)
事件监听
绑定方法:
-
HTML 元素属性:
写在元素的开始标签内,键值对形式,事件类型为属性,事件函数为属性值。例如:
<input onclick="alert('Wow!')"> -
DOM 对象属性:
var btn = document.getElementById('btn'); btn.onclick = function (){ alert('Wow!') }
常用的鼠标事件类型:
- onclick 鼠标左键单击触发
- ondbclick 鼠标左键双击触发
- onmousedown 鼠标按键按下触发
- onmouseup 鼠标按键放开时触发
- onmousemove 鼠标在元素上移动触发
- onmouseover 鼠标移动到元素上触发
- onmouseout 鼠标移出元素边界触发
DOM 元素属性操作
非表单元素的属性的操作#10
元素对象中已经封装了与元素属性同名的方法,方便直接调用,例如 href、title、id、src 等。
部分属性名由于与 js 关键字和保留字冲突,需要更换写法:
- class → className
- for → htmlFor
- rowspan → rowSpan
更改属性值: 以字符串类型,通过等号赋值
(注意:id 属性只读)
【案例】
-
点击按钮切换图片#11
-
点击按钮显示隐藏元素#12
- 通常以修改类名的方式。结合 CSS,两个类选择器分别实现隐藏和显示。
补充说明:事件函数内部的 this #13
普通函数 → window 对象
构造函数 → 生成的实例对象
对象的方法 → 对象本身
事件函数 → 事件源 -
相册切换
innerHTML 和 innerText
- innerHTML:适用于设置有内部子标签结构
读取时,包含内部的元素标签、空白换行;
写入时,按照 HTML 语法加载内容,字符实体会转义为符号显示。 - innerText:适用于设置纯字符串
读取时,过滤掉元素标签、换行缩进等,只保留文字内容;
写入时,加载为普通字符,所写即所示。
表单元素属性的操作#17
表单元素多为单标签元素,无法使用 innerHTML 或 innerText(双标签元素<option>除外),通常 value 可以用于大部分表单元素的内容获取。
type 属性可以获取 <input> 元素的类型。
另外,一些特殊的属性,比如:disabled、checked、selected 等,它们的属性值只有一个且与属性名相同。在 js 中读取或赋值时,使用布尔值,true 表示打开。
【案例】
-
检测用户名和密码案例#18
- onfocus 事件
-
随机设置下拉菜单选中项#19
-
搜索文本框#20
-
全选反选#21-23
自定义属性的操作#24
支持自定义属性,但是没有特别对应的方法可供调用,而需要使用通用方法调用。以下几种方法适用于任何属性的操作。
- 获取 getAttribute(name)
- 设置 setAttribute(name,value)
- 移除 removeAttribute(name)
作为参数的属性名和属性值均为字符串格式。
【单列】style 属性的操作#25
element.style 获取到的值是,由所有行内样式组成的样式对象,CSSStyleDeclaration.
element.style.attribute 可以进一步调用到该元素行内样式的某一具体 CSS 属性的数据。
注意:类似 background-color 的包含连字符的单一属性需要改写为驼峰命名法,即 body.style.backgroundColor。
【小结】js 中有关样式的操作#26
截至目前,在 js 中需要修改样式主要由两种方法:
修改类名适用于批量的、通用的样式,方便。同时需要注意层叠性。
修改 style 属性值适用于细节变化的修改,精确。
【综合案例】
-
开关灯#27
- 有可利用的值做判断条件时,可省略一个判断变量
-
显示隐藏二维码#28
- onmouseover、onmouseout 事件
- 目标元素有多个类名时,使用字符串的 replace 方法进行替换
string.replace('a','b')将 string 中的 a 替换为 b,并返回
-
当前输入的文本框高亮显示#29
- 排他思想:排除其他;保留自己
做法:先排除所有(需要遍历),再单独做自己
- 排他思想:排除其他;保留自己
-
点击按钮改变 div 的大小和位置#30
-
表格隔行变色、高亮显示#31
-
tab 选项卡切换#32-33
- 对应控制:两组数据中存储同样数量的元素对象,一组变换,引起另一组也变化。
- 为了实现一一对应,即两个数组同下标位置的元素之间的同步。在为每一个子项元素绑定事件的遍历中,前置添加一个自定义属性存储它在数组中的下标,而后在事件函数中即可调用该自定义函数获取下标。
Step3:DOM 节点操作
节点的属性#35
- nodeType 节点类型
只读- 值:
- 1:元素节点
- 2:属性节点
- 3:文本节点 另有其他值,见手册。
- 值:
- nodeName 节点名称
只读 - nodeValue 节点值
- 值:
- 元素节点的节点值:null
- 属性节点的节点值:该 HTML 属性的属性值
- 文本节点的节点值:其文本
- 值:
节点的层级关系
类似于 HTML 元素间的族谱关系,节点的层级关系主要可分为父子关系和兄弟关系。
父子节点常用属性#36
-
childNodes 该节点下所有子节点的集合
返回值 NodeList;只读;动态 -
children 该节点下所有子元素节点的集合
返回值 HTMLCollection;只读;动态 -
firstChild 第一个子节点
lastChild 最后一个子节点
只读;如果没有子节点,返回 null -
firstElementChild 第一个子元素节点
lastElementChild 最后一个子元素节点 -
parentNode 当前节点的父节点 如果该节点位于 DOM 树顶端(如 document),或尚未插入一棵树中(如 新生成的节点),那么它返回 null
-
parentElement 当前节点的父元素节点
如果该元素没有父节点,或父节点不是一个 DOM 元素节点,则返回 null。
【案例】表格隔行变色重写#37
使用节点的方法获取到元素节点,而【#31】中的则是获取到元素。 二者效果类似,但分属不同体系。
兄弟节点常用属性#38
-
nextSibling
只读属性,返回与该节点同级的下一个节点,如果没有返回null。
previousSibling
只读属性,返回与该节点同级的上一个节点,如果没有返回null。 -
nextElementSibling
只读属性,返回与该节点同级的下一个元素节点,如果没有返回null。
previousElementSibling
只读属性,返回与该节点同级的上一个元素节点,如果没有返回null。- 注意:nextElementSibling 和 previousElementSibling 有兼容性问题,IE9 以后才支持
节点的操作
创建新节点的方法
- document.createElement("div") 创建元素节点,参数为元素名
- document.createAttribute("id") 创建属性节点,参数为属性名
- document.createTextNode("hello") 创建文本节点,参数为文本 通常来说,要创建变量存储创建出来的节点
节点的添加、替换、插入、删除、克隆#40-42
-
parentNode.appendChild(child)
将一个节点添加到指定父节点的子节点列表末尾。 参数 child 可以是新建的节点,也可以是已存在的节点,那么即实现“剪切”效果。 -
parentNode.replaceChild(newChild, oldChild)
用指定的节点替换当前节点的一个子节点,并返回被替换掉的节点。 -
parentNode.insertBefore(newNode, referenceNode)
在参考节点之前插入一个拥有指定父节点的子节点。 referenceNode 必须设置,如果为 null 则 newNode 将被插入到子节点的末尾,相当于 appendChild() -
parentNode.removeChild(child)
移除当前节点的一个子节点。
这个子节点必须存在于当前节点中 -
Node.cloneNode()
克隆一个节点- 参数:Boolean 布尔值
- true:深度克隆,该节点的所有后代节点都会被克隆
- false:浅度克隆,只克隆该节点本身 不建议省略参数
- 注意:标签上的属性和属性值都会被复制,其中包括作为元素写在标签行内的绑定事件,而通过 JavaScript 动态绑定的事件不会被复制
- 参数:Boolean 布尔值
节点的判断方法#43
-
Node.hasChildNodes()
没有参数,返回一个 Boolean 布尔值,来表示该元素是否包含有子节点(不区分节点类型) -
Node.contains(child)
返回一个 Boolean 布尔值,来表示传入的节点是否为该节点的后代节点(包含关系,而不局限在父子关系)
判断一个节点有无子节点的方法:
node.firstChild !== nullnode.childNodes.length > 0node.hasChildNodes()以上三个表达式的值均为布尔,true 表示有,false 表示无。
【案例】
- 动态创建列表#44
- 动态创建表格#45-46
- 选择水果#47-48
Step4:DOM 事件详解
使用键值形式的事件绑定不能多次绑定。
注册/绑定事件的其他方法
element.addEventListener()#49
- 参数:
- 第一个参数:事件类型的字符串(不加'on',只写'click')
- 第二个参数:事件函数
- 说明:此方法可以绑定多个事件,响应时会按代码先后顺序执行。
- 兼容性:不支持 IE 8 及以下
element.attachEvent()#50
- 参数:
- 第一个参数:事件类型的字符串(一般写法的事件类型)
- 第二个参数:事件函数
- 兼容性:IE 11、Chrome 不支持,仅支持 IE 10 及以下,且 IE 8 及以下处理事件列队时会出现顺序错乱
绑定兼容写法#51
自行封装一个函数,内部做浏览器能力判断
function addEvent(ele,type,fn){
//有监听器能力的 IE 9 及以上使用
if (ele.addEventListener) {
ele.addEventListener(type,fn);
}
//只有附加事件能力的 IE 8 及以下使用
else if (ele.attachEvent) {
ele.attachEvent('on'+type,fn);
}
}
函数的三个参数分别是事件源、事件类型和事件函数
事件移除的方法
DOM 0级:
给事件赋 null 值
DOM 2级:
element.removeEventListener()
element.detachEvent()
分别对应前述的两种绑定方法
不能移除匿名函数,所以需要解绑的事件,在绑定时必须是被定义了的函数。
解绑兼容写法#53
function removeEvent() {
if (ele.addEventListener) {
ele.addEventListener(type,fn);
} else if (ele.attachEvent) {
ele.attachEvent('on'+type,fn);
}
}
【tips】诸如上述的两个兼容浏览器的绑定/解绑函数,这些常用的自定义函数可以写入一个js文件作为公共库引入
DOM 事件流#54
事件冒泡过程默认顺序为:从内层到外层,底层向上冒泡 事件捕获过程:从外层向内层,顶层先捕获向下传导
addEventListener() 有第三个参数,布尔值,决定事件流的方向。 true 事件捕获过程;false 事件冒泡过程(默认值)
先执行捕获,后执行冒泡
DOM 事件流的三个阶段#55
- 第一个阶段:事件捕获
- 第二个阶段:事件执行过程
- 第三个阶段:事件冒泡
onclick 事件类型,只能进行事件冒泡过程,没有捕获阶段
attachEvent() 方法:只能进行事件冒泡过程,没有捕获阶段
事件冒泡的应用:事件委托#56
将子级的事件委托给父级加载,子级触发事件时会向上冒泡到父级,而父级绑定的事件中可以找到那个触发事件的子级。
适用于多个子级元素的公共类型事件。
father.onclick = function (e) {
e.target.atrribute = 'attr';
}
这里利用了事件函数的内置参数e,它存储着事件的真正事件源。
此例中,e 代表了事件对象;target 是事件的触发元素。
这样的事件委托有效节省代码,无需遍历多个同级元素添加类似事件。
事件对象#57-58
展开讲一讲上例中提到的事件对象:
-
e.eventPhase 查看事件触发时所处的阶段
-
e.target 用于获取触发事件的元素
e.srcElement 用于获取触发事件的元素,低版本浏览器使用
兼容写法:var target = e.target || e.srcElement; -
e.currentTarget 用于获取绑定事件的事件源元素
事件函数中,this 指向等同为 e.currentTarget -
e.type 获取事件类型
值:不带on
使用场景:需要对一个元素对象添加不同的事件类型时,以一个共同的函数作为事件函数,函数内以 e.type 作判断条件。避免了分别定义多个函数,以节省内存优化性能。function fn(e) { switch (e.type) { case 'mouseover': break; case 'mouseout': break; } } -
e.clientX/e.clientY 事件触发时,鼠标距离浏览器窗口左上角的距离(即鼠标在浏览器窗口中的坐标)
-
e.pageX/e.pageY 事件触发时,鼠标距离整个HTML页面左上顶点的距离
兼容性:IE8 及以下不支持
注意:e 在低版本浏览器中有兼容问题,低版本浏览器等效使用的是 window.event
因此,兼容写法为 e = e || window.event
【案例】图片跟随鼠标移动#59
取消默认行为和阻止冒泡#60
【小结】阻止默认行为:
- 在事件函数结尾
return false; e.preventDefault();取消默认行为e.returnValue = false;取消默认行为,低版本浏览器使用
阻止冒泡:
e.stopPropagation();阻止冒泡,标准方式e.cancelBubble = true;阻止冒泡,IE 低版本,标准中已废弃
Step5:DOM 特效
offset 系列属性#61
- offsetParent
偏移参考父级,距离自己最近的有定位的父级,如果都没有定位参考body(html),类似于 CSS 中绝对定位的参考元素 - offsetLeft、offsetTop
- offsetWidth、offsetHeight
边框及以内(border、padding、content)的宽高,类似于 CSS 中 border-box 模式下的width和height
client 系列属性#62
- clientLeft、clientTop
左边框和上边框的尺寸,不常用 - clientWidth、clientHeight
边框以内(padding、content)的宽高
通常,在有边框时选用 offsetWidth & offsetHeight,没有边框时选用 clientWidth & clientHeight
scroll 系列属性
- scrollLeft、scrollTop
- scrollWidth、scrollHeight
【案例】
- 拖拽#64
- 弹出层#65