——————————
JavaScript··[API]
「DOM」
——————————
DOM
什么是DOM
文档对象模型,是由W3C组织推荐的一种处理可扩展标记语言(xml)的标准编程接口。
XML和HTML:
XML:可扩展标记语言,主要是通过自定义标签进行对数据保存处理
HTML:超文本标记语言,是一些已经规定好的一套标签
W3C已经定义好了一系列的DOM接口,我们目前主要通过这些DOM接口进行改变网页内容、结构和样式
DOM的内容
DOM中最大最原始的对象是文档对象
DOM的结构其实就是一个HTML的标准文档结构
文档-HTML:根元素
- head元素
- title元素
- mate元素
- …
- body元素
- h1-h6
- div
- …
文档:一个页面就是一个文档,一个文档在DOM中使用document表示
节点:网页中的所有内容,在文档中所有的节点(标签、属性、文本、注释等),使用node表示
标签节点:网页中所有的标签,通常称为元素节点,也叫作元素,用element表示
总结:以上的所有内容在DOM中都是以对象的方式表示
获取元素
-
getelementById:通过元素的Id值获取对应的元素,只能获取当前文档中的一个指定的元素
首先在html中严格意义上来说不允许两个标签有相同的Id值,其次这个函数只会在html中找到第一个这个Id值的元素就会将元素返回
注意:如果没有获取到则返回一个null
-
getElementByName:通过元素的Name属性值获取对应的元素,将该文档中的所有的与该Name属性值元素都获取到,并且将获取到的所有元素装在一个NodeList里面,即使只有一个元素,也是装在NodeList里面的
注意:如果没有获取到一个元素则返回的NodeList[],空列表
-
getElementsByTagName:通过元素的元素名称获取对应的元素,将该文档中的所有的这个命名的元素都获取到,并且将获取到的所有元素装在一个HTMLCollection里面,即使只有一个元素,也是装在HTMLCollection里面
注意:如果没有获取到一个元素则返回的HTMLCollection[],空集合
-
【H5新增】getElementsByClassName:通过元素的Class属性值获取到对应的元素,将该文档中所有的与该class属性值匹配的元素都获取到,并且将获取到的所有元素装在一个HTMLCollection里面
注意:如果没有获取到一个元素则返回的HTMLCollection[],空集合
因为获取元素的最终结果是一个伪数组,因此在使用元素的时候需要遍历
而且得到的元素对象是动态的,当页面里面增加了标签,集合中的元素也会增加
【H5新增】
-
根据选择器进行获取
var a=document.querySelector(".like");
只会找到和选择器匹配的第一个元素
-
根据选择器进行获取
var a=document.querySelectorAll(".like");
会找到所有的和选择器匹配的元素,并返回一个元素列表NodeList
【获取特殊元素(html,body)】
-
var a=document.body;//获取body元素
-
var a=document.documentElement;//获取html元素
事件的使用
事件的概念
简单理解为:需要进行触发,触发之后会进行一些响应工作
JS中帮助我们创建动态页面,或者对页面中的内容起到侦测的行为。基本上每个元素都有一些事件操作,当我们触发了事件的机制,那么就可以进行一些其他操作
事件的条件
- 主角(事件源):触发事件的元素
- 发生什么事(事件类型):比如单击click
- 做了什么(事件处理程序):事件触发后执行的代码(函数)。这个函数就是在这格元素被触发了对应的事件后自己执行的函数。
执行事件的步骤
- 获取事件源
- 绑定事件
- 添加事件的处理程序
- 运行并触发事件
<div id="mydiv">
这是一个div
</div>
<script>
window.onload=function(){
// 获取事件源
var mydiv=document.querySelector("#mydiv");
// 绑定事件
mydiv.onclick=function(){
// 添加程序
alert("你好");
}
}
常用的事件
鼠标事件
- onclick:鼠标点击左键触发
- onmouseover:鼠标经过时触发
- onmouseout:当鼠标离开时触发
- onmousemove:当鼠标移动时触发
- onmousedown:当鼠标按下时触发
- onmouseup:当鼠标弹起时触发
- onfocus:当获取到鼠标焦点时触发
- onblur:当失去鼠标焦点时触发
键盘事件
- onkeyup:当某个按键被松开的时候后触发
- onkeydown:当某个按键被按下的时候触发
- onkeypress:当某个按键被按下的时候触发,不识别功能按钮(方向键、shift)
注意:
- 如果使用addEventListener不需要加on
- onkeypress和前面的两个事件区别在于它不识别功能键
- 三个时间的触发顺序是:keydown–keypress–keyup
键盘事件对象
属性:
KeyCode:返回该键的ASCII码值
- keydown和keyup事件对象是同样的,事件不区分字母大小写(大写),keypress会区别大小写
- 在实际开发中,使用更多的是keydown和keyup,能够识别所有按键
- keypress识别大小写返回大小写不同的ASCII码
作用:使用keyCode属性判断用户的按键操作
操作元素
JS中的DOM操作主要可以改变网页的内容、结构(标签)、样式。可以使用DOM操作元素来改变元素里面的内容、属性等,同样这些操作针对于DOM而言也是通过操作对象的属性来实现的
改变元素里的内容
<input type="text" value="请输入一个内容" id="txt">
<h3 id="myh3"><u>改变之前的内容</u></h3>
<h2 id="myh2"><u>改变之前的内容</u></h2>
<b id="myb">a</b>
<script>
window.onload=function(){
var txt=document.getElementById("txt");
txt.onmousedown=function(){
txt.value="改变之后";
}
var h3=document.querySelector("#myh3");
h3.onmousedown=function(){
h3.innerText="改变之后";
}
var h2=document.querySelector("#myh2");
h2.onmousedown=function(){
h2.innerHTML="改变之后";
}
var b=document.getElementById("myb");
b.onmousedown=function(){
b.innerHTML="<u>这是下划线</u>";
}
}
</script>
-
对于文本框而言,其内容属于value属性的值
-
对于其他标签内容指的是写在两个标签之间的内容部分,所以无法使用value属性实现
-
解决这个问题使用两个节点对象属性
- 元素的innerText属性
- 元素的innerHTML属性
这两个属性都可以修改一个节点之间的内容,对于HTML文件而言能够识别"<>",如果内容里面有"<>",则对于HTML文件而言可能会将这个内容字符串里面的"<>"当成标签处理。
标签是指:以"<“开头,并且以字母或者”/“作为尖括号内部内容开头,以”>"结束的组合称为标签。而在HTML文件中对于标签如果是标准的html标签则按照html作用实现,如果不是则只显示其标签之内的文本,不显示标签。
两者区别
-
innerText
在获取内容操作时,不会将内部的标签进行字符串处理,不会获取标签
在设置内容时,会将字符串直接输出到页面不会解析内容中的"<>",并且会保留字符串内的空格及换行。
-
innerHTML
在获取内容操作时,会将其内部的所有标签及内容全部进行字符串处理并返回
在设置内容时,会将字符串里面的"<>"进行解析然后再体现到页面中,不会会保留字符串内的空格及换行。
常用元素属性操作
- innerText、innerHTML:改变元素之间的内容
- src:改变元素的资源路径,将资源直接下载并加载到这个界面中
- href:改变元素的链接资源,直接跟随这个路径找到资源
- id、alt、title
获取元素属性:元素.属性名
设置元素属性:元素.属性名=属性值
表单元素的属性操作
利用DOM进行对页面内的表单元素的属性进行操作
例如:value、type、checked、selected、disabled
获取元素属性:元素.属性名
设置元素属性:元素.属性名=属性值
注意:在设置这些属性的时候disabled、checked、selected属性的值是布尔类型
操作样式
可以用DOM操作获取到元素对象之后,同时可以使用JS对元素的样式(大小、颜色、位置等)进行操作
常用方式
- element.style开始对style(样式)的内容进行操作
- element.className 通过对类名进行样式操作
通过style属性操作样式
- 元素对象的style属性也是一个对象
- 通过对元素的style进行样式属性=值
- JS里面样式命名方式采取的是驼峰命名法:backgroundColor
- JS修改style样式操作,产生的是行内样式,CSS权重这里的高
通过操作className属性
- 元素对象.className=值,使用className并非class,因为JS里面的class是特殊关键字
- 如果样式修改的比较多,利用这种方式修改更为方便
- className会直接更改元素的class属性的内容,会覆盖原始的class值,如果不想覆盖则使用多类名
自定义属性
可以在使用DOM操作元素的时候,可以给元素添加一些其原本没有的属性,来记录一些数据
获取属性值
- 元素对象.属性名 获取属性值
- 元素对象.getAttribute(属性名) 获取属性值
区别:通过对象名点属性名获取到的是元素的属性值,并且对css属性以css形式返回。不能获取到自定义属性的值
通过getAttribute获取属性值,返回的结果是以字符串体现,可以获取到自定义属性的值
设置属性值
- 元素对象.属性名=属性值
- 元素对象.setAttribute(属性名,属性值);//属性名完全按照元素原本的属性名设置,否则将是自定义属性
区别:通过元素对象.属性名=属性值只能设置元素对象原有的一些属性,无法设置自定义属性
通过元素对象.setAttribute(属性名,属性值)可以设置任何属性
作用
使用自定属性来让标签自己记录一些不保密的数据,但是又要跟随元素的变化而变化的数据
移除属性
元素对象.removeAttribute(属性名)
H5自定义属性
自定义属性目的:是为了保存一些数据,有些数据可以保存到页面里而这些数据不需要保存到服务器数据库中。
自定义属性获取和创建基本上都是通过和Attribute有关的两个函数实现
自定义属性有可能会产生很多的歧义,并且不是很好区分到底是标签原有属性还是自定义属性
H5新增了自定义属性:
规则
- H5里面规定自定义属性必须以data-开头作为属性名称并且赋值
- 获取H5自定义属性和设置自定义属性依然使用Attribute函数
- 在H5里面新增了元素名称.dataset.属性名称或者元素名称.dataset[属性名称],在IE11里面才能被支持,这里使用的属性名称不包含data-,dataset属性会将这个元素的所有自定义属性全部以键值对的方式保存起来
节点操作
节点概述
网页页面中的所有内容都是节点(标签、属性、文本、注释等),在DOM中节点以Node来表示
在使用DOM操作对节点实现修改、添加、删除操作
一般情况下,节点至少拥有三个基本属性
- nodeType:节点类型,这里的类型是标签的名称
- nodeName:节点名称,这里的名称是js中给这个节点起的一个名字
- nodeValue:节点值
创建节点
document.createElement(“div”)
document.createElement(tagName)方法创建由tagName指定的HTML元素,因为这些元素原先不存在document里面,而是根据我们的需求动态创建的,所以这种创建方式的元素叫做动态节点
同时创建的节点需要添加到HTML文档中
添加节点
- node.appedChild(节点),方法将一个节点元素添加到指定的父节点中的最后一个子节点之后
- node.insertBefore(节点,子节点),方法将一个节点元素添加到指定的父节点中的指定子节点之前
节点层级
利用DOM将节点划分为不同的层级关系,常见的层间关系就是父子关系
一般操作包含以下:
-
父级节点:node.parentNode
-
子级节点:
-
node.childNodes(标准),返回包含指定子节点的集合,这个集合会进行即时更新
注意:
返回值里面包含了所有的子节点包括孙子级别,还包含有文本节点,如果只想要获取里面的元素节点,需要专门处理。因此一般不用这个方式
-
parentNode.children(非标准),是一个只读属性,返回所有的子元素节点,它只返回子元素节点,不会返回浏览器的格式化节点
之后主要使用这个属性
-
-
第一个子节点:parentNode.firstChild
返回第一个子节点,找不到则返回null,同样包含文本节点
-
最后一个子节点:parentNode.lastChild
返回最后一个子节点,找不到则返回null,同样包含文本节点
-
第一个子元素节点:parentNode.firstElementChild
返回第一个子元素节点,找不到则返回null,只找元素,IE9之后
-
最后一个子元素节点:parentNode.lastElementChild
返回最后一个子元素节点,找不到则返回null,只找元素,IE9之后
-
兄弟节点:
上一个元素兄弟节点:self.previousElementSibling
下一个元素兄弟节点:self.nextElementSibling
上面两个只管元素问题,有兼容问题
上一个兄弟节点:self.previousSibling
下一个兄弟节点:self.nextSibling
上面两个找所有的节点包含文本节点
排他思想
- 先找到所有的元素
- 消灭所有的元素样式,改成初始样式
- 然后留下自己,设置特定样式
注意:顺序不能颠倒,先消灭后自己
window.onload=function(){
// 【1】选择所有的相关元素
// .getElementsByTagName("li")
var lis=document.querySelectorAll(".choose>li");
// lis是一个伪数组(对象),里面的每一个元素进行遍历
for(var i=0;i<lis.length;i++){
lis[i].onclick=function(){
// 【2】先进行全部消灭,将所有的背景颜色先全部改为初始颜色
for(var j=0;j<lis.length;j++){
lis[j].style.backgroundColor="azure";
}
// 【3】然后留下自己,将当前点击的这个元素的背景颜色进行单独改变
// this代指当前事件的所属元素自身,当前自身绝对不能用lis[i]代表
this.style.backgroundColor="pink";
}
}
}
元素的创建总结
元素的创建
- document.write();
- element.innerHTML();
- document.createElement();
区别
- 使用document.write是直接将内容写入到页面的内容流区域,当文档流执行完毕,会导致页面全部重绘
- element.innerHTML:是将内容写入当前这个节点内部,并且不会导致页面重绘,还可以创建多个元素,工作效率更高,(不需要连接字符串操作),但是写法结构比较复杂
- document.createElement,创建元素但是只是创建了非结构中的元素,不会自动添加到结构内部,并且创建多个元素效率比较低,但是结构简单清晰
事件高级内容
事件是什么
这个元素所具备的一些被动能力,当这个元素被进行某种程度的触发之后进行对某些函数进行处理执行,将这种触发叫做元素的事件
注册事件
给元素添加事件,称为注册事件或者绑定事件
注册事件的两种方式;传统方式、监听注册方式
传统方式
- 元素对象有一些on开头的事件onclick
- 第一步找到这些事件
- 第二步给这些时间直接赋值一个函数,或者直接给事件赋值要处理的代码
特点:注册事件的唯一性,同一个元素同一个事件只能设置一个处理函数,当前注册的处理函数将会覆盖前面注册的处理函数
监听注册方式
- W3C标准推荐的一种注册事件方式
- 第一步给元素对象使用addEventListener()
特点:IE9和之前的版本不支持这种方式,在旧版本里面使用的是attchEvent()代替,同一个元素同一个事件可以注册很多个监听事件并且按照绑定顺序依次执行
三个参数:
- type:事件类型字符串
- listener:事件的处理函数,事件发生时所调用的函数
- options:可选参数,是一个布尔值,作用和事件流有关
删除事件
传统方式
btn.οnclick=null;
监听注册方式
btn.removeEventListener(“click”,say);
btn.detachEvent()这个删除事件方法和attchEvent()注册事件方法对应
事件流
html标签都是一些相互嵌套的盒子,document是最大的盒子,考虑一个问题:
-
如果牵扯到盒子嵌套问题,外盒子和内盒子都有相同的一个事件,问题是如果这两个盒子的事件同时触发结果怎样?
两个事件都会触发,顺序从里到外
-
如果这个盒子默认由属于自己的事件例如a标签,那么当重新给此事件注册一个函数触发之后结果怎样?
跳转>aa>bb
事件流描述的是从页面中接收事件的顺序
事件发生时会在元素节点之间按照特定的顺序传播触发,这个传播过程叫做DOM事件流
事件冒泡:IE提出的,事件开始时是由最具体的元素接收,然后逐级向上级传播到DOM的最顶层节点的过程
事件捕获:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到最具体的元素接收的过程
W3C最终做出统一协调:先捕获再冒泡
当今的浏览器对于DOM事件流经过3个阶段:
- 捕获阶段:检查具有这个事件的所有元素从外到内都有哪些
- 当前目标阶段:事件当前的处理者
- 冒泡阶段:按照从内到外的顺序进行事件冒泡
注意:
- JS代码中只能执行捕获或者冒泡其中的一个阶段
- onclick和attachEvent,只能得到冒泡阶段
- addEventListener第三个参数如果是true,表示在事件捕获阶段调用事件处理函数。如果是false,表示在事件冒泡阶段处理程序
- 实际开发中很少使用事件捕获,更关注的是事件冒泡
- 有些事件是没有冒泡,比如onblur,onfocus,onmouseenter,onmouseleave
- 事件冒泡在实际开发中某些时候会产生一系列问题需要注意。
事件对象
事件发生后,跟事件相关的一系列信息数据的集合都放在一个对象里面,这个对象称为事件对象
- 谁绑定了这个事件
- 鼠标触发事件的话,会得到鼠标的相关数据
- 键盘触发事件的话,会得到键盘的相关数据,键盘事件只有可以获取焦点的元素可以使用
使用
事件触发是就会自动产生这个对象,并且会自动跟随事件函数的参数传递,会当做事件函数的实参传递给函数内部,所以要使用事件对象则给事件绑定的函数需有一个形参,这个形参来接受事件对象。(旧版本中,基本上是通过浏览器中的window对象寻找event,再获取相关对象)
事件对象属性
e.keyCode:键盘事件键盘按下时按键的大写字母的ASCII码
e.key:键盘事件键盘按下时按键的键值
e.clientX:鼠标相对于浏览器窗口可视区域的X坐标
e.clientY:鼠标相对于浏览器窗口可视区域的Y坐标
e.pageX:鼠标相对于当前Document文档的X坐标,IE9以上
e.pageY:鼠标相对于当前Document文档的Y坐标,IE9以上
e.screenX:鼠标相对于电脑屏幕的X坐标
e.screenY:鼠标相对于电脑屏幕的Y坐标
e.target:返回触发事件的对象(标准)
e.srcElement:返回触发事件的对象(非标准)
e.type:返回触发事件的事件类型
e.cancelBubble:该属性阻止事件冒泡(非标准)
e.returnValue:该属性阻止默认事件(非标准)
e.preventDefault():该方法阻止默认事件(标准)
e.stopPropagation():该方法阻止事件冒泡(标准)
注意:e.target是事件触发的元素,this是事件的绑定元素
事件委托
事件冒泡本身的特性会带来很多问题,在某种情况下也会带来很多好处
将事情委托给别人,别人代为处理
事件委托:事件代理,简单理解为不给子元素注册事件,给父元素注册事件,把处理代码在父元素的事件中执行
委托的原理
给父元素注册事件,利用事件冒泡,当子元素的事件触发,最后会冒泡到父元素,然后控制响应的子元素
委托的使用
-
只操作一次DOM,提高程序的性能
-
动态创建的子元素也拥有事件
<ul> <li>点击列表项有惊喜</li> <li>点击列表项有惊喜</li> <li>点击列表项有惊喜</li> <li>点击列表项有惊喜</li> <li>点击列表项有惊喜</li> </ul> <script> window.onload=function(){ var ul=document.querySelector("ul"); ul.addEventListener("click",function(e){ e.target.style.backgroundColor="pink"; }); } </script>
事件冒泡和默认事件
- 阻止默认事件:e.preventDefault();
- 阻止事件冒泡:e.stopPropagation();
- 两个都阻止: return false;(原生JS里面无法阻止事件冒泡)