DOM(document Object Model),文档对象模型(是什么,可以用来干什么)
1. DOM方法 1.1 getElementById- 返回指定id的第一个对象
var div = document.getElementById("div");//返回id值为div的元素
1.2 getElementsByTagName
- 返回指定的标签名的一个类数组对象(因为返回的值是一个类数组,可以理解成多个对象,所以方法名中用Elements)
- 如果只要其中的某一个,可以用数组中的方括号来访问(起始下标为0)
- 想知道一共有几个,可以用length属性
var div = document.getElementsByTagName("div");//返回所有div元素组成的类数组对象
var div1 = document.getElementsByTagName("div")[0];//返回所有div元素中的第一个
var len = div.length;//返回div元素的数量(Number类型)
1.3 getAttribute
- 获取元素的指定的某一个属性
var mydiv = document.getElementById("div");
var iden = mydiv.getAttribute("id");//获得ID为div元素的ID属性值
1.4 setAttribute
- 设置元素的属性(包括了添加和修改,设置为空也可以理解成删除)
var mydiv = document.getElementById("div");
mydiv.setAttribute("class","mydiv");//把div元素的class属性值设置为mydiv
1.5 removeAttribute
- 删除元素的属性
var mydiv = document.getElementById("div");
mydiv.removeAttribute("class");//删除div元素的class属性,即为空
2. DOM属性
2.1 style
- 设置元素的CSS样式
var myDiv = document.getElementById("div");
div.style.background="blue";//ID值为div的元素的背景颜色被设置成为蓝色
2.2 innerHTML
- 返回元素标签内部的HTML(注意不一定是文档),可以理解成“读取”
- 设置元素标签内部的HTML,可理解成“写入”
var mydiv = document.getElementById("div");
var inner = mydiv.innerHTML;//获取ID为div的元素的内部的内容
//如果有内部嵌套标签则连同嵌套标签和文档一并返回
mydiv.innerHTML = "Hello, world
"//内部套上p标签,文本内容为hello,world
2.3 className
- 返回元素的class属性值,可理解成“读取”
- 设置元素的class属性值,可理解成“写入”
var mydiv = document.getElementById("div");
mydiv.className;//返回ID为div元素的class属性,未设置时,控制台无输出
mydiv.className = "mydiv";//给div元素设置class属性为mydiv
3. DOM事件
事件,即文档/浏览器窗口发生的一些特定的交互瞬间
3.1 鼠标事件 3.1.1 onload- 在页面加载完毕时触发
- 适用于script标签放在head部分时/针对文档内部标签相应的事件(必须在文档加载好之后才触发事件)
window.onload=function(){}//页面加载完毕后运行匿名函数function内部指令
3.1.2 onclick/onmouseover/onmouseout
- 鼠标点击时/移动到元素上方时/移出元素时触发
var div = document.getElementById("div");
function myalert1(){alert("你的鼠标放在一个div上面");}
var myalert = function myalert2(){alert("你已经移出了div");}
div.onclick=function(){alert("你点击了一个div");}
div.onmouseover=myalert1();
div.onmouseout=myalert;//鼠标移入后移出时触发,注意此处只要用变量名,不需要函数名
3.1.3 onmousedown/onmouseup/onmousemove
- 鼠标按下/松开/移动指针时触发
- onmousedown、onmouseup合在一起成就了onclick事件
- 发生顺序为:onmousedown、onmouseup、onclick
var div = document.getElementById("div");
div.onmousemove=function(){console.log("你在div里面移动了");}//在div里移动,控制台打印
div.onmousedown=function(){console.log("你点击了div");}
div.onmouseup=function(){console.log("你松开了div");}//点击和松开时控制台打印
3.1.4 onfocus/onblur
- 获得/失去焦点时触发
- 适用于input标签中type为text、password的以及textarea标签
var username = document.getElementById("username");
//当光标在username输入框,执行函数
username.onfocus=function(){p.innerHTML="请输入用户名!");}
//当光标离开username输入框,执行函数
username.onblur=function(){p.innerHTML="用户名输入正确!";)}
3.1.5 onchange
- 域的值发生变化时触发
- 主要适用于select下拉菜单、radio单选、checkbox多选
//根据选项调整页面的背景颜色
function changeBack(){
var div1 = document.getElementById("mydiv");
var menu = document.getElementById("changeColor");
menu.onchange=function(){
//可通过下拉菜单的options来创建类数组,通过selectedIndex访问选定的元素下标
var bg = menu.options[menu.selectedIndex].value;
div1.style.background=bg;
}
}
window.onload=changeBack;//注意事件触发时调用函数无需()
3.1.6 onsubmit
- 表单中确认按钮被点击时触发
- 该事件添加在表单元素上,而不是提交按钮上
3.1.7 onresize/onscroll
- 当窗口大小发生变化/滚动条滚动时触发该事件
- 两个事件常常用在window对象上,但也可以用在div等块级元素上
- 在按下按键/按下键盘按键(字母、数字、符号、回车、空格)/松开按键时发生
- 发生顺序为onkeydown、onkeypress、onkeyup
- 可用keyCode属性返回按下键的编码
- 创建元素节点
- 该方法创建的HTML5标签是可以兼容IE8以下的浏览器的
- IE6-8下可以创建HTML中不存在的标签
//创建一个li节点
var li = document.createElement("li");
4.1.2 createTextNode
- 创建文本节点
//创建一个text节点并把其添加到li节点中
var text = document.createTextNode("hello world");
li.appendChild(text);
4.1.3 createdocumentFragment
- 创建文档片段
- 创建目的:在DOM树中,文档片段被其所有的子元素所代替。 因为文档片段存在于内存中,并不在DOM树中,所以将子元素插入到文档片段时不会引起页面回流(对元素位置和几何上的计算)。因此,使用文档片段通常会带来更好的性能
- 创建注释(极少用)
- 创建标签内部的HTML文档,可以添加文本也可以添加标签和属性,以字符串形式传入即可
- 读取标签内部的HTML文档,包括标签、属性、文本、注释等
- 限制:
- IE6-8中,传入的字符串左侧的空白会被自动删除
- 只有IE8及更早版本可以在script内部传入内容后执行script内部脚本,但script元素得有defer属性,且script前必须为有作用域元素(即不可为空)
- IE8及以前的浏览器
- 包括了父节点下的所有元素(包括自己)
- 只读取指定元素内部的文本,忽略其他(标签、属性、注释等)节点
- 写入时,会把标签一并当做文本写入
- IE4以上、Safari3以上、opera8以上、chrome支持,火狐不支持(有特有的textContent属性)
我是div
我是p标签
- li1
- li2
- li3
//对所有类型的浏览器通用的innerText方法
//读取版本
function getInnerText(element){
if(typeof element.textContent == "string"){
return element.textContent;
}
else{
return element.innerText;
}
}
//写入版本
function writeInnerText(element,text){
if(typeof element.textContent == "string"){
text = element.textContent;
}
else{
text = element.innerText;
}
}
4.1.8 outerText
- 读取时,同innerText功能一致
- 写入时,会把调用元素的子节点(包括子节点)全部替换掉
- 由于使用后会导致调用改属性的元素不再存在,不建议使用
- DOM文档也是一棵树,以document为根,包括了多种节点
- 父节点到子节点:firstChild、lastChild、childNodes[i]、childNodes.item(i)
- 子节点到父节点:parentNode
- 子节点之间:nextSibling、previousSibling
- 返回文档根节点:documentElement、ownerdocument(任意元素直接返回)
- 返回元素标签名:tagName
- 判断一个节点是否有子节点:hasChildNodes()
//思路:判断当前节点是否有子节点,如果有则重复调用函数,遍历所有子节点,否则结束
var s = "";
//space为传入的连接符号,node为建树的起始节点
function travel(space,node){
if(node.tagName){
s += space + node.tagName + "
";
}
var len = node.childNodes.length;
for(var i = 0;i < len;i++){
travel(space+"*",node.childNodes[i]);
}
}
travel("",document);
document.write(s);
4.2.5 节点遍历时的问题及方法(空白节点)
4.2.5.1 问题的原因
- childNode属性中,IE8以前的浏览器会忽略标签之间的空格
- 新浏览器会把这些空格当成节点
- 因此,遇到HTML.childNodes[1]时,浏览器识别出的不是body而是text
- 删除空白(不建议)
- 用tagname属性判断(不建议)
- 用nodeType属性(1为元素,2为属性,3为文本)
- 父节点到子节点(从标签到标签):firstElementChild、lastElementChild、children[i]
- 子节点之间(从标签到标签):nextElementSibling、previousElementsSibling
- 返回所有子节点个数(只是子节点):childElementCount
- childNodes里保存着的对象
- 不是array实例,没有数组对象方法,只是保存一组有序节点
- 访问值可用方括号,方法和属性包括:
- item方法
- length属性
- 如果想把NodeList中内容转换成真的数组对象,可以用以下两种方法:
- Array对象的prototype属性下的slice方法(低版本IE运行时会报错)
- 元素循环遍历后输出
function makeArray(nodelist){
var arr = null;
try{
return Array.prototype.slice.call(nodelist);//把nodelist转换成数组
}
catch(e){
arr = new Array();
for(var i=0,len=nodelist.length;i
4.3.2 HTMLCollection
- 表示HTML元素的集合
- 会返回HTMLCollection的常用属性和方法有:
- getElementsByTagName:返回指定标签的集合
- document.scripts:返回document里所有script元素集合
- document.links/images/forms:返回页面中所有a/图片/表单元素
- tr.cells:返回该表格的tr的所有td
- select.options:返回select的所有选项
- td.namedItem:在该表格元素集合中先找id为指定名的元素,若没有,找第一个name为指定名的元素,返回元素
- 方法和属性有:
- item方法
- length属性
- namedItem方法:在该元素集合下找id为指定名称的元素,若没有,找第一个name为指定名的元素,返回元素
我是div1
我是div2
我是div3
4.3.3 namedNodeMap
- 通过访问元素的attributes属性得到,返回元素节点特性的集合
- 常用方法和属性有:
- item:返回某一个元素节点特性
- length:返回元素节点特性数量
4.3.4 类数组对象的动态性
- Nodelist、HTMLColletcion、NamedNodeMap都是基于DOM结构动态查询的结果,DOM结构只要有变化,其也会相应发生变化
- 文档结构更新,三者都会更新,因此三者保存最新、最准确信息
4.4 节点查找
4.4.1 getElementById
- 返回id属性值为给定值的标签元素
- IE低版本浏览器中会把在id值为查找值之前name值为查找值的元素找出来
- 文本里设定两个id值相同的元素时,会查找到第一个
- 只可通过document对象来调用
这个是错误的元素
这个才是正确的元素
这个是另一个正确的元素
- 解决getElementById的bug(针对IE)的方法
- 避免在同一页面文档里出现同一名称的name和id(有时较难)
- 用document.all方法来解决
//思路:获取元素后判断该元素的id是否显示设置
//是的话,判断id是否为该值,如果不是该值,用document.all方法来获取文档中
//所有name和id为指定值的元素,一个个判断id值是否为给定值
var getElementById = function(id){
var el = document.getElementById(id);
//此处,v在IE中被解析为v,其他浏览器中解析为垂直制表符(可理解成空格)
//v1随后被转化为字符串v1/数字1,加号试图转化为数字(IE转化成NaN)
//取反后IE为true,其他为false
if(!+"v1"){
if(el && el.id === id){return el;}
else{
var els = document.all[id],
n = els.length;
for(var i = 0;i < n;i++){
if(els[i].id === id){return els[i];}
}
}
}
return el;
}
4.4.2 getElementsByName
- 返回指定name属性值的一个类数组对象
- 只可通过document对象来调用
- 在IE6和Opera7.5上有bug
- 返回id为给定值的元素
- 仅对input和image元素起作用
4.4.3 getElementsByTagName
- 返回指定标签名的所有元素的一个类数组(传入值不区分大小写)
- 传入参数为!时,返回注释节点
- IE6-8下,文档类型声明也被当成了注释
- Chrome不支持该方法
- 传入参数为*时,返回页面上的所有元素
4.4.4 getElementsByClassName
- 返回指定class值的所有元素的一个类数组
- 传入多个class名时,用空格隔开
- Firefox3、Chrome、IE9、Safari4以上可以使用
- 解决兼容性问题的方法
//思路:(未完待续)
4.4.5 querySelector
- 以CSS选择器的方法来选择元素(.调用类,#调用id)
- 可以用任意元素来调用该方法(document或文档子节点)
- 找不到元素时,返回null
- 几乎所有主流浏览器都支持(IE8及以上支持)
4.4.6 querySelectorAll
- 返回一个查找的元素的集合staticNodelist(静态的类数组,数组第一次查找完后不会因为DOM的变化而实时更新)
- 当找不到元素时,返回一个空的集合
- 几乎所有主流浏览器都支持(IE8及以上支持)
4.5 节点操作
4.5.1 appendChild
- 在指定元素最后一个子节点后添加节点,返回新添加的节点
- 如果添加的是已经存在的子元素,则会把这个子元素移动到最后
- 1
- 2
- 3
- 4
4.5.2 insertBefore
- 把指定节点放到指定的节点的前面
- 传入的第二个参数为null时,可以把节点添加到最后(相当于appendChild)
- 1
- 2
- 3
4.5.3 replaceChild
- 替换一个子节点,返回这个替换的节点
ul.replaceChild(li,li2);//把ul里的li2替换成li
4.5.4 cloneNode
- 克隆一个节点,返回这个父本
- 传入参数true时,复制其中的子节点(默认为false)
4.5.5 normalize
- 把文本节点合并
hello
world
4.5.6 splitText
- 按照指定的位置,把一个文本节点分割成两个
- 返回新的文本节点
helloworld
4.6 删除节点
4.6.1 removeChild
- 删除某个节点中指定的子节点
- 传入的参数为删除的节点,且该方法必须传入参数
- 同innerHTML的“删除”比较:
- IE6-8,removeChild为掰断树枝,但树枝还可以继续用
- IE6-8,innerHTML为把树枝拔下来,烧掉
- Chrome浏览器,两者都只是掰断树枝
4.6.2 removeNode
- 把目标节点从文档中删除,返回删除的节点
- 参数为布尔值,默认为false(只删除目标节点,保留其下的子节点)
- 只在IE中起作用
5. DOM属性
5.1 属性介绍
- 固有属性property:浏览器捆绑好的属性
- 自定义属性attribute:自己设置的属性
- 同名的属性,以先定义的为准
- 属性名称全部为小写
- 无法通过元素后的属性访问,只能用getNamedItem()方法以及nodevalue属性访问属性值
- 不可通过console.log()方法输出,输出结果为undefined
5.2 方法和属性
5.2.1 getNamedItem()
- 该方法返回指定的属性节点
- 不能访问没有显式定义的属性,即便是固有属性也不可以
5.2.2 attributes
- 返回指定节点的属性集合
- 可通过.attributes[i].nodevalue访问某个节点第i个属性值
5.2.3 removeNamedItem()
- 删除一个属性,参数为待删除属性的名字
5.2.4 setNamedItem()
- 把创建好的属性添加到指定的元素上
var div = document.getElementById('div');
var test1 = document.createAttribute("xxx");
test1.nodevalue='hello';
div.attributes.setNamedItem(test1);//把test1这个属性值添加到div元素上
5.2.5 getAttribute()
- 操作固有属性和自定义属性的通用方法
- 获得指定属性名的属性值
- style、onclick属性用getAttribute和属性(div.style)获取时,返回值会不同
- 一般用JS来操作DOM时,不使用getAttribute方法,只有在取自定义属性的值时才使用getAttribute
5.2.6 setAttribute()
- 设置元素属性值,两个参数(属性名,属性值)
- IE7及更早版本不支持
5.2.7 removeAttribute()
- 删除属性
- 兼容IE6
5.3 布尔属性
- 传入的属性值参数会进行隐式的类型转换
- 常用的有:
- radio和checkbox中的checked
- option标签中的selected
- input的type值为text的readonly(设置属性时readOnly记得O大写)
- disabled
- select中的multiple
- hidden
5.4 data属性
- 用来存储页面/应用程序私有定义的属性
- 用dataset属性来获取data属性的值
- 一个-直接用名字(data-toggle)
- 多个-用驼峰式写名称(data-xxx-yyy变成dataXxxYyy)
5.5 classList
- IE11及以上才支持
- 方法:
- add:添加
- remove:移除
- has:判断是否存在
- toggle:存在就移除,不存在就添加



