前端——DOM
什么是DOM?
DOM是W3C(万维网联盟)的标准,是Document Object Model(文档对象模型)的缩写,它定义了访问HTML文档(也用于XML,这里不管XML)的标准:
“W3C文档对象模型(DOM)是中立于平台和语言的接口,它允许程序和脚本动态地访问和更新文档的内容、结构和样式。”
DOM标准被分为三个不同的部分:
- 核心 DOM - 针对任何结构化文档的标准模型
- XML DOM - 针对XML文档的标准模型
- HTML DOM - 针对HTML文档的标准模型
什么是HTML DOM?
- HTML 的标准对象模型
- HTML 的标准编程接口
- W3C 标准
HTML DOM 定义了所有 HTML 元素的对象和属性,以及访问它们的方法。将整个HTML当做一个对象,对象嵌套对象,形成一个树形结构,每个标签都认为是一个对象。
换言之,HTML DOM 使用对象来描述一个 HTML 文档。我们最为关心的是,DOM把网页和脚本以及其他编程语言联系了起来。
DOM API 大致包含4个部分:
- 节点:DOM 树形结构中的节点相关 API
- 事件:触发和监听事件相关 API
- Range:操作文字范围相关 API
- 遍历:遍历 DOM 需要的 API
节点相关 API
查找节点
1.直接查找
document.getElementById() 根据ID获取标签(单个标签) document.getElementsByName() 根据name属性获取标签(列表) document.getElementsByTagName() 根据标签类型获取标签(列表) document.getElementsByClassName() 根据class属性获取标签(列表) document.querySelector() 允许通过CSS选择器的规则来查找标签(符合条件的第一个) document.querySelectorAll() 所有符合条件的(列表)
需要注意的是:
1.getElementsByName、getElementsByTagName、getElementsByClassName 获取的集合并非数组,而是一个能够动态更新的集合。 var collection = document.getElementsByClassName('hello'); console.log(collection.length); var hello= document.createElement('div'); winter.setAttribute('class', 'hello') document.documentElement.appendChild(winter) console.log(collection.length); 2.querySelector虽然很强大,但性能不如getElement系列
2.间接查找
间接查找是建立在直接查找的结果基础之上的操作
parentNode // 父节点 childrenNodes // 子节点们 firstChild // 第一个子节点 lastChild // 最后一个子节点 nextSibling // 下一个兄弟节点 previousSibling // 上一个兄弟节点 parentElement // 父元素 children // 所有子元素 firstElementChild // 第一个子标签元素 lastElementChild // 最后一个子标签元素 nextElementSibling // 下一个兄弟标签元素 previousElementSibling // 上一个兄弟标签元素
操作节点
创建元素
document.createElement(tagName, ...options) 创建新元素,返回它
插入
appendChild 将DOM元素添加到指定元素内部最后一个,并返回新节点 insertBefore 将DOM元素插入到指定元素后面,返回新节点 insertAdjacentHTML 将字符串文本解析为HTML,将其插入到指定位置 insertAdjacentElement 将DOM元素插入到指定位置
详细说明:
node.appendChild(element) node.insertBefore(newNode, referenNode) 将新节点 newNode 插入父节点内部,referenNode是引用节点,相当于参照物,插在它的前面,也可以传入null将被插入到末尾。第二个参数必须显式地传入。 element.insertAdjacentHTML(position, text) element.insertAdjacentElement(position, element) 两者的区别在于,前者传入文本字符串,后者传入element。 position是相对与元素的位置,必须是以下几个字符串之一: beforebegin、afterbegin、beforeend、afterend分别表示添加到对照元素的前面、内部第一个、内部最后一个、后面
删除
removeChild(node) 删除,并返回该节点
删除API要删除元素,必须要获得它本身和父元素,常用的办法是这样:
tag.parentElement.removeChild(tag);
替换
parentNode.replaceChild(newChild, oldChild) 新节点替换旧节点,返回被替换的节点
其它
node.cloneNode(deep) 克隆node节点,返回副本。参数deep可选,boolean,是否克隆后代节点 node.compareDocumentPosition(otherNode) 可以比较当前节点与任意文档中的另一个节点的位置关系,有返回值 node.contains(otherNode) 判断otherNode是否为node的后代节点,返回布尔值 element.hasChildNodes() 当前节点是否含有子节点,返回布尔值 node.isEqualNode(otherNode) 比较两个节点是否是相等的节点,类型相同、特征、属性、文本内容等等都相同时,才会认为相等。 nodeA === nodeB 判断两个节点是否是同一个节点
节点相关的属性
attribute 属性操作
attributes 获取所有属性 getAttribute(name) 获取某属性的值 setAttribute(name, value) 设置属性 removeAttribute(name) 删除属性 hasAttribute(name) 判断是否有该属性
文本内容操作
.innerText 获取标签文本内容 .innerText=" " 对文本内容重新赋值 .inerHTML 获取标签全部内容 .innerHTML=" " 设置标签全部内容 .value (只对部分标签生效)获取input中(所有使用value)的值、select标签选中的值,textarea标签中的值 .value=" " 设置值 .checked 获取单(复)选框中的值,input标签中类型checked,radio的专属 .checked=" " 设置值,true 或 false
注意:
inner/outer HTML 与 inner/outer Text 的区别:
例如:如对于这样一个HTML元素:<div>content<br/></div> innerHTML:内部HTML字符串,content<br/>; outerHTML:外部HTML字符串,<div>content<br/></div>; innerText:内部文本,content ; outerText:内部文本,content ,与innerText的区别是,outerText赋值时会把标签一起覆盖
样式操作
class类
className 获取所有使用的类 className="样式" 设置样式(会覆盖之前的,处理方法与.cssText相同) className.indexOf("样式") 判断是否具有某样式,有则返回下标,没有返回-1 classList.add(class) 增添样式集合 classList.remove(class) 删除样式 classList.item(class) 根据索引返回类值 classList.contains(class) 检查有无该类值 classList.replace(oldClass, newClass) 替换类值
style样式
.style.属性 = "值"; 对具体样式进行操作 例如:.style.color = "red"; .style.cssText = ""; 可以一次性设置多个样式。 例:.style.cssText = "width:180px;color:white;height:40px;" 有了.cssText可以一步完成,但是会带来一个问题,会把原来有的样式清除掉,例如原来有的css中有style“display:none;”,在执行完上面的js操作后,display会被删掉,解决办法: .style.cssText += ";width:180px;color:white;height:40px;"
获取样式
window.getComputedStyle(element, pseudoElt) 获取元素计算之后的样式属性值,即当前元素最终使用的所有CSS属性值。返回值是一个实时更新的 CSSStyleDeclaration 对象,当元素样式更改时,它会自动更新。 如果不需要获取伪元素,第二个参数省略,默认null 获取伪元素示例:getComputedStyle(element, '::after')
写完整的CSS
let style = document.createElement('style'); style.innerHTML = 'body{color:red} #top:hover{background-color: red;color: white;}'; document.head.appendChild(style);
这里是关于样式的基本操作,更丰富的样式操作请看:XXX
Range API
Range API 表示一个 HTML 上的范围,这个范围是以文字为最小单位的,所以 Range 不一定包含完整的节点,它可能是 Text 节点中的一段,也可以是头尾两个 Text 的一部分加上中间的元素。我们通过 Range API 可以比节点 API 更精确地操作 DOM 树,凡是节点 API 能做到的,Range API 都能做到,而且可以做到性能更高。但是 Range API 用起来比较麻烦,所以在实际项目中并不常用,只有做底层框架和富文本编辑对它有强需求。
事件
要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素相应的事件绑定处理函数。
示例:
// 鼠标移入移出显示不同效果,可以用CSS hover实现
<body> <table id="text" border = "1"> <tr><td>1</td><td>2</td><td>3</td></tr> <tr><td>1</td><td>2</td><td>3</td></tr> <tr><td>1</td><td>2</td><td>3</td></tr> </table> <script> var tag = document.getElementsByTagName("tr"); var len = tag.length; for(var i=0;i<len;i++) { tag[i].onmouseover = function(){ //tag[i].style.backgroundColor = "red"; //会报错,要将tag[i]换成this:谁调用这个函数,this就指向谁、 // 作用域的问题 this.style.backgroundColor = "red"; } tag[i].onmouseout = function(){ this.style.backgroundColor = ""; } } </script> </body>
// 输入框默认显示提示信息,点击消失。 标签中placeholder属性可以实现类似效果,不同的是:点击不消失,输入字符时才消失。
<body> <div> <input onfocus="Focus();" onblur="Blur();" id="i1" type="text" value="请输入关键字"> </div> <script> function Focus(){ var tag = document.getElementById("i1"); if(tag.value == "请输入关键字") { tag.value= ""; } } function Blur(){ var tag = document.getElementById("i1"); if(tag.value.length == 0) { tag.value = "请输入关键字"; } } </script> </body>
绑定事件:
在JavaScript和DOM的知识背景下有三种绑定事件的方式:
1.在HTML标签中直接绑定(不建议)
初学者使用的方法,为简化html代码,不建议使用。
<div onclick="click(this)"> // 一般函数不需要传入参数,如果多个标签绑定同一函数,为了区分用户点击的是哪个标签,需要传入this function click(self){ // self 代指当前点击的标签 }
2.先获取DOM对象,再进行绑定
可使JavaScript代码与HTML相分离,文档结构清晰,便于管理和开发。
// 绑定函数 document.getElementById("i1").onclick = function(){ this 代指当前点击的标签 } // 解除函数 document.getElementById("i1").onclick = null;
3.绑定/解除事件监听函数
可以对一个事件绑定多个函数
a. addEventListener()方法(推荐)
// 绑定事件监听函数 addEventListener() document.getElementById("i1").addEventListener("click",function(){},false); document.getElementById("i1").addEventListener("click",handle,false); 参数:事件名称,执行函数,执行模式。 关于执行模式:默认false表示冒泡阶段执行,true表示捕捉阶段执行。 // 解除事件监听函数 removeEventListener() 参数与上相同。需要注意 1.该方法只能移除由addEventListener()方法添加的函数 2.匿名函数无法移除
b, attachEvent()方法
attachEvent("事件名称","执行函数")