JavaScript DOM
1 概述
W3C定义了一系列DOM接口,DOM接口可以改变网页的内容、结构、样式。
DOM树中,文档Document为最高级别的父元素,代表整个html页面;其子元素为html标签,html子元素为head和body标签。每个标签都有其属性和内容。
DOM树中,所有的元素都可称之为节点,DOM将其作为对象看待。
2 获取元素
//本质上是由父元素对象获取子元素对象,不会获取父元素,获取时,父元素对象必须是确定的单个元素,不能是数组。
//得到的元素是动态的,改变html内时,无需更改js代码。
//获取元素时,可以嵌套使用方法,例:document.getElementById('id名').querySelector('标签名');
(1) 通过id获取
//返回值为指定id的对象(一个对象)。var 对象名 = 父元素对象名.getElementById('id名');console.dir(对象名);
//该打印方式可以更好地查看对象中的属性和方法。
(2) 通过标签名获取
//返回值为指定标签名对象的伪数组(多个对象的集合)。
//即使该标签名的对象只有一个或没有,仍返回伪数组或空伪数组。var 对象名 = 父元素对象名.getElementByTagName('标签名');console.dir(对象名[0]);
遍历伪数组
for(var i ; i < 对象名.length ; i++){
console.log(对象名[i]);
}
(3) 通过HTML5新增方法获取
<1> 通过类名获取
//返回值为指定类名对象的伪数组(多个对象的集合)。var 对象名 = 父元素对象名.getElementByClassName('类名');console.dir(对象名[0]);
<2> 通过选择器获取第一个元素对象
//返回值为指定选择器的第一个元素对象。var 对象名 = 父元素对象名.querySelector('#id/标签名/.类名');console.dir(对象名);
<3> 通过选择器获取所有元素对象
//返回值为指定选择器的所有元素对象的集合。var 对象名 = 父元素对象名.querySelectorAll('#id/标签名/.类名');console.dir(对象名[0]);
(4) 对于特殊元素的获取
<1> 获取html标签
var htmlEle = document.documentElement;console.dir(htmlEle);
<2> 获取body标签
var bodyEle = document.body;console.dir(bodyEle);
3 添加事件
(1) 概述
为某个元素添加某个事件,当事件发生时,执行某段代码。
基本组成:事件源、事件类型、事件处理程序。
(2) 执行事件的步骤
<1> 获取事件源
即 获取元素对象
//获取元素对象时,既要获取事件源的元素对象,也要获取事件处理程序所需要的元素对象,即被操作的元素。
<2> 绑定事件
//语法格式:元素对象.事件类型,例:divEle.onclick。onclick:鼠标点击左键触发onmouseover:鼠标经过触发onmouseout:鼠标离开触发onfocus:获得鼠标焦点触发onblur:失去鼠标焦点触发onmousemove:鼠标移动触发onmouseup:鼠标弹起触发onmousedown:鼠标按下触发
<3> 添加事件处理程序
元素对象.事件类型 = function(){
操作元素(改变元素的属性与内容);
//在该函数中若出现this,表示函数当前调用者,即元素对象。
}
4 操作元素
//如果有多个*相同操作*的*同类型*元素,可以先使用getElementByTagName()或querySelectorAll()获取此元素对象集合,再使用for循环来操作元素。
(1) 修改元素内容
//语法格式:元素对象名.innerText = '修改后的内容';
//将innertext和innerhtml理解为元素对象的两个属性。
<1> 元素对象所对应标签中的所有内容,但会去除html标签、空格及换行。
//innerText不识别HTML标签元素对象名.innerText
<2> 元素对象所对应标签中的所有内容,不会去除html标签、空格及换行。
//innerHTML识别HTML标签元素对象名.innerHTML
<3> innerText和innerHTML既可以修改标签中的内容,也可以获取标签中的内容。var text = 元素对象名.innerText;console.log(元素对象名.innerText); //获取标签中的内容元素对象名.innerText = '修改后的内容'; //修改标签中的内容
(2) 修改元素属性
//该方式通常修改*自带属性*,例如src、href、id、title、alt等属性。
语法格式:元素对象名.属性名 = '修改后的值'; //注意加单引号,属性的值应为字符串。
//标签的属性相当于元素对象的属性,使用方式也与对象属性相同。
(3) 修改表单元素的属性
<1> 修改表单类型:表单元素对象名.type
<2> 更改表单中的内容:表单元素对象名.value
//不可使用innerText或innerHTML。
<3> 禁用表单:表单元素对象名.disabled = true
(4) 修改样式属性
//该方式通常修改*自定义属性*,例如元素的大小、颜色、位置。
//本质上是修改元素对象style属性的属性。
<1> 行内样式操作:元素对象名.style.属性名 = '修改后的值';
//为该元素添加了行内式样式,权重较高。
//对于html中的属性采取驼峰命名法,比如backGroundColor、frontSize。
案例:精灵图背景
// 核心思路:首先精灵图图片排列有规律的,利用for循环修改精灵图片的背景位置background-position,让循环里面的i索引号*第一个图片的y坐标。
var lis = document.querySelectorAll('li');
for(var i=0;i<lis.length;i++){
var index = i * 第一个图片的y坐标;
lis[i].style.backgroundPosition = '0 -' + index + 'px';
}
<2> 类名样式操作:元素对象名.className = '类名';
清除类名样式:元素对象名.className = '';
//将当前元素的类名改为了所写类名。
//可以通过更改当前元素类名的方式修改更多元素的属性,适用于更复杂的情况。
//该方式会直接修改类名,覆盖原有类名,若要保留原有类名并添加新样式:元素对象名.className = '旧类名 新类名';
(5) 排他思想
案例:一组按钮中,只为当前所点击的按钮设置背景颜色。
//1.获取所有按钮元素
var btns = document.getElementsByTagName('button');
//btns得到的是伪数组,里面的每一个元素为btns[i]。
for(var i=0;i<btns.length;i++){ //为每个按钮添加相同的事件。
btns[i].onclick = function(){
//2.首先先排除其他人,然后才设置自己的样式。
//(1) 点击时,首先将所有的按钮背景颜色去掉。
for(var i=0;i<btns.length;i++){
btns[i].style.backgroundcolor = '';
}
//(2) 然后为当前点击元素设置背景颜色。
this.style.backgroundcolor = 'pink';
}
}
(6) 自定义属性
<1> 自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
<2> 但是有些自定义属性很容易引起岐义,不容易判断是元素的内置属性还是自定义属性。H5规定自定义属性以data-开头做为属性名并且赋值。
//比如<div data-index = "1">
(7) 自定义属性的操作
<1> 获取属性值
<1.1> var 属性名 = element.属性名;
<1.2> var 属性名 = element.getAttribute('属性名');
<1.3> var 属性名 = element.dataset.属性名;或者var 属性名 = element.dataset['属性名']; //属性名必须去掉'data-'。
//dataset是一个集合里面存放了所有以data-开头的自定义属性。
//H5新增方法,ie11开始支持。
<1.4> 区别:
① element.属性名;获取内置属性值(元素本身自带的属性)。
② element.getattribute('属性名');和element.dataset.属性名;主要获得自定义的属性(我们程序员自定义的属性)。
<2> 设置属性值
<2.1> element.属性名 ='值';
<2.2> element.setAttribute('属性名','值');
<2.3> 区别:
① element.属性名;设置内置属性值(元素本身自带的属性)。
② element.getattribute('属性名');主要设置自定义的属性(我们程序员自定义的属性)。
<3> 移除自定义属性
element.RemoveAttribute('属性名');
(8) 节点操作
<1> 概述
<1.1> 获取元素通常使用两种方式:利用DOM提供的方法获取元素、利用节点层级关系来获得元素。
<1.2> 网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node来表示,所有节点都可以通过js进行增删改查。
<1.3> 一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
<1.4> 元素节点nodeType为1,属性节点nodeType为2,文本节点nodeType为3(文本节点包含文字、空格、*换行*等)。
//我们在实际开发中,节点操作主要操作的是元素节点
<2> 节点层级
<2.1> 父级节点
//返回值为一个对象。var 对象名 = 节点对象.parentNode
① parentNode属性可返回某节点的父节点,注意是最近的一个父节点。
② 如果指定的节点没有父节点则返回null。
<2.2> 子级节点
//返回值都为一个集合。
① var 对象名 = 父节点对象.childNodes
返回包含指定节点的所有子节点的集合,该集合为即时更新的集合。
//换行字符也算一个节点,通常标签内第一个子节点都为换行符为文本的文本结点。
注意:返回值里面包含了*所有的子节点*,包括元素节点,文本节点等,所以我们一般不提倡使用childNodes,如果只想要获得里面的元素节点,则需要专门处理。
var ul = document.querySelector('ul');
for(var i = 0;i < ul.childNodes.length;i++){
if(ul.childNodes[i].nodeType == 1){ //若ul的子节点为元素节点。
console.log(ul.childNodes[i]);
}
}
② var 对象名 = 父节点对象.children
parentNode.children是一个只读属性,返回所有的子元素节点。
注意:它只返回*子元素节点*,其余节点不返回(这个是我们重点掌握的)。
//虽然children是一个非标准,但是得到了各个浏览器的支持,可以放心使用。
③ var 对象名 = 父节点对象.firstChild
返回第一个子节点,找不到则返回null。同样,也是包含所有的节点(标签、属性、文本、注释等)。
④ var 对象名 = 父节点对象.lastChild
返回最后一个子节点,找不到则返回null。同样,也是包含所有的节点(标签、属性、文本、注释等)。
⑤ var 对象名 = 父节点对象.firstElementChild
返回第一个子元素节点,找不到则返回null。
//该方法有兼容性问题,IE9以上才支持。
⑥ var 对象名 = 父节点对象.lastElementChild
返回最后一个子元素节点,找不到则返回null。
//该方法有兼容性问题,IE9以上才支持。
⑦ 获取第一个或最后一个子元素节点并解决兼容性问题。
若要获得第一个子元素节点,可以使用 var 属性名 = 父节点对象.children[0];
若要获得最后一个子元素节点,可以使用 var 属性名 = 父节点对象.children[父节点对象.children.length - 1];
<2.3> 兄弟节点
//返回值为一个对象。
① var 对象名 = 节点对象.nextSibling
返回当前元素的下一个兄弟节点,找不到则返回null。同样,也是包含所有的节点(标签、属性、文本、注释等)。
② var 对象名 = 节点对象.previousSibling
返回当前元素上一个兄弟节点,找不到则返回null。同样,也是包含所有的节点(标签、属性、文本、注释等)。
③ var 对象名 = 节点对象.nextElementSibling
返回当前元素下一个兄弟元素节点,找不到则返回null。
//该方法有兼容性问题,IE9以上才支持。
④ var 对象名 = 节点对象.previousElementSibling
返回当前元素上一个兄弟节点,找不到则返回null。
//该方法有兼容性问题,IE9以上才支持。
⑤ 获取上一个或最下一个兄弟元素节点并解决兼容性问题。
//返回当前元素下一个兄弟元素节点,找不到则返回null。
function getNextElementSibling(element){
var el = element;
while(el = el.nextSibling){
if(el.nodeType === 1){
return el;
}
}
return null;
}
<3> 创建节点
var 对象名 = document.createElement('标签名');
创建由标签名指定的HTML元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
<4> 添加节点
<4.1> 父节点对象.appendChild(节点对象);
将一个节点添加到指定父节点的子节点列表末尾。
//类似于css里面的after伪元素。
<4.2> 父节点对象.insertBefore(节点对象,指定子节点);
将一个节点添加到父节点的指定子节点前面。
//类似于css里面的before伪元素。
我们想要页面添加一个新的元素,首先创建元素,然后再添加元素。
<5> 删除节点
父节点对象.removeChild(节点对象);
从DOM中删除一个子节点,返回删除的节点。
<6> 复制节点(克隆节点)
<6.1> 父节点对象.cloneNode();
返回调用该方法的节点的一个副本。也称为克隆节点/拷贝节点。
<6.2> 如果括号参数为空或者为false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
<6.3> 如果括号参数为true,则是深度拷贝,会复制节点本身以及里面所有的子节点。
<7> 动态创建表格
var body = document.querySelector('tbody');
//data为一个对象数组。
for(var i=0;i<data.length;i++){
//创建行
var tr =document.createElement('tr');
tbody.appendChild;
//创建每行的列,列数取决与对象中属性的个数。
for(var k in data[i]){
//遍历对象属性,k为属性名称。
var td=document.createElement('td');
tr.appendChild(td);
td.innerHTML=data[i][k];
//i为对象数组的索引,data[i]是一个对象。
//k为对象的属性名,data[i][k]是对象的属性值。
tr.appendChild(td);
}
//每行最后一列为删除链接
var td=document.createElement('td');
td.innerHTML='<a herf="javascript:;">删除</a>';
tr.appendChild(td);
}
var as=document.querySelector('a');
//获取所有a元素
for(var i=0;i<as.length;i++){
as[i].onclick=function(){
tbody.removeChild(this.parentNode.parentNode);
//点击a标签,删除a元素的父元素(tr)的父元素(td)。
}
}
<8> 三种动态创建元素区别
<8.1> document.write("html标签+文字")是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘。
<8.2> element.innerHTML()是将内容写入某个DOM节点,不会导致页面全部重绘。
//innerHTML创建多个元素效率更高(不用拼接字符串,采取数组形式拼接),结构稍微复杂。
var array=[];
for(var i=0;i<100;i++){
array.push("<div style="width:100px"></div>")
}
document.body.innerHTML=aray.join('');
//join:将数组转化为字符串。
<8.3> document.createElement()创建多个元素效率稍低一点点,但是结构更清晰。
for(var i=0;i<100;i++){
var div =document.createElement("div");
document.body.appendChild(div);
}
//总结:不同浏览器下,innerHTML效率要比creatElement高。

浙公网安备 33010602011771号