js中的事件获取与节点操作
JS Web API
API的概念
API是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,无需理解其内部工作机制细节,只需直接调用使用即可。
Web APIs的概念
Web API是浏览器提供的一套操作浏览器功能和页面元素的API(BOM 和 DOM)
API和Web API总结
- API是为程序员提供的一个接口,帮助我们实现某种功能。
- Web API 主要针对浏览器提供的接口,主要针对浏览器做交互效果。
- Web API一般都有输入和输出(函数的传参和返回值),WebAPI很多都是方法(函数)
- 学习API可以结合前面学习内置对象方法的思路学习
DOM介绍
文档对象模型(Document Object Model,简称DOM),是处理可扩展标记语言的标准编程接口。
DOM树
DOM数 又称为文档数模型,把文档映射成树形结构,通过节点对象对其处理,处理的结果可以加入到当前的页面。
- 文档:一个页面就是一个文档,DOM中使用document表示
- 节点:网页中的所用内容,在文档树中都是节点(标签、属性、文本、注释等),使用node表示
- 标签节点:网页中的所有标签,通常成为元素节点,又简称为“元素”,使用element表示
获取元素
根据ID获取
语法:docuemnt.getElementById(“id”)
作用:根据ID获取元素对象
参数id值,区分大小写的字符串
返回值:元素对象 或 null
<div id=one></div>
<script>
var one = document.getElementById("one");
one.style.backgroundColor="red"
one.style.width="100px"
one.style.height="100px"
</script>
根据标签名获取元素
语法:document.getElementsByTagName(“标签名”)
作用:根据标签名获取元素对象
参数:标签名
返回值:元素对象集合(伪数组,数组元素是元素对象)
<div></div>
<div></div>
<div></div>
<script>
var one = document.getElementsByTagName("div");
//控制台查看返回数组
console.log(one)
//循环输出
for(var i = 0; i<one.length; i++ ){
one[i].style.width='100px';
one[i].style.height="100px"
one[i].style.backgroundColor="red"
}
H5新增获取元素方式
-
document.getElementsByClassName(“类名”)//根据类名返回数组对象集合
<div class="one"></div> <div class="one"></div> <div class="one"></div> <script> var one = document.getElementsByClassName("one") console.log(one) </script>
-
document.querySelector(“选择器”)//根据指定选择器返回第一个元素对象
<div class="one"></div> <div class="one"></div> <div class="one"></div> <script> var one = document.querySelector(".one") console.log(one) </script>
-
document.querySelectorAll(“选择器”)//根据指定选择器返回
<div class="one"></div> <div class="one"></div> <div class="one"></div> <script> var one = document.querySelectorAll(".one") console.log(one) </script>
获取特殊元素(body,html)
获取body元素
document.body
document.body.style.backgroundColor="red"
获取html元素
document.documentElement
document.documentElement.style.color="red"
事件基础
事件三要素
-
事件源(谁):触发时间的元素
-
事件类型(什么事件):例如click点击事件
-
事件处理程序(做什么):事件触发后要执行的代码
<button>点击事件</button> <script> var btn = document.querySelector("button") btn.onclick = function(){ alert("我在这") } </script>
常见的鼠标事件
事件 | 说明 |
---|---|
onClick | 鼠标点击事件,多用在某个对象控制的范围内的鼠标点击 |
onfocus | 获得鼠标焦点 |
onblur | 失去鼠标焦点 |
onMouseOut | 当鼠标离开某对象范围时触发的事件 |
onDblClick | 鼠标双击事件 |
onMouseDown | 鼠标上的按钮被按下了 |
onMouseUp | 鼠标按下后,松开时激发的事件 |
onMouseOver | 当鼠标移动到某对象范围的上方时触发的事件 |
onMouseMove | 鼠标移动时触发的事件 |
键盘事件
事件 | 说明 |
---|---|
onkeydown | 按下键盘时运行脚本 |
onkeypress | 按下并松开时运行脚本 |
onkeyup | 事件会在键盘按键被松开时发生 |
操作元素
改变元素内容
element.innerText
从起始位置到终止位置的内容,但去除html标签
<button>点击事件</button>
<script>
var btn = document.querySelector("button")
btn.onclick = function(){
btn.innerText="<strong>我变粗了</strong>"
}
element.innerHTML
从起始到终止位置的全部内容,包括html标签
<button>点击事件</button>
<script>
var btn = document.querySelector("button")
btn.onclick = function(){
btn.innerHTML="<strong>我变粗了</strong>"
}
区别
- 获取内容时
- innerText会去除空格和换行,innerHTML会保存
- 设置内容时的区别
- innerText不识别HTML,innerHTML会识别
案例:点击获取当前时间
<button>点击</button>
<div>显示时间</div>
<script>
var btn = document.querySelector("button")
var time = document.querySelector("div")
btn.onclick = function(){
time.innerHTML= getDate();
}
function getDate(){
var date= new Date();
var year = date.getFullYear();
var month = date.getMonth()+1;
var dates = date.getDate();
var day = date.getDate();
var arr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六']
return `今天是:${year} 年 ${month} 月 ${dates} 日 ${arr[day]}`
}
</script>
常用的元素的属性操作
- inneText、innerHTML
- src、href
- id、alt、title
表单属性操作
type、value、checked、selected、disabled
获取元素的值
元素对象.属性名
设置属性的值
元素对象.属性名 = 值
表单元素中有一些属性如disabled、checked、selected,元素对象的这些属性的值是布尔型
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
table {
border-collapse: collapse;
width: 800px;
}
th,
td {
border: 1px solid #000;
padding: 15px;
/* width: 100px; */
text-align: center;
}
.active {
background: rgb(240, 111, 111);
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th><input id='all' type="checkbox"></th>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
</tr>
</thead>
<tbody>
<tr>
<td><input class='cbox' type="checkbox"></td>
<td>1</td>
<td>小明</td>
<td>18</td>
</tr>
<tr>
<td><input class='cbox' type="checkbox"></td>
<td>2</td>
<td>小明</td>
<td>18</td>
</tr>
<tr>
<td><input class='cbox' type="checkbox"></td>
<td>3</td>
<td>小明</td>
<td>18</td>
</tr>
</tbody>
</table>
</body>
<script>
var trs = document.querySelectorAll('tbody tr');
var all = document.querySelector("#all")
var cbox = document.getElementsByClassName("cbox")
// 全选
all.onclick = function () {
for (var i = 0; i < cbox.length; i++) {
cbox[i].checked = this.checked;
}
}
//反选
for(var i = 0; i < trs.length; i++){
trs[i].onclick= function(){
var flag = 1;
for(var i = 0; i<trs.length; i++){
if(!cbox[i].checked){
flag = 0;
break
}
}
all.checked=flag
}
}
//悬浮背景
for (var j = 0; j< trs.length; j++) {
trs[j].onmouseover = function () {
this.className = 'active'
}
trs[j].onmouseout = function () {
this.className = ''
}
}
// for (var i = 0; i < trs.length; i++) {
// if (i % 2 == 0) {
// trs[i].style.background = ' yellow'
// } else {
// trs[i].style.background = 'purple'
// }
// }
</script>
</html>
样式属性操作
element.style 行内样式操作
element.className 类名样式操作
自定义属性操作
- element.属性 获取内置属性值
element.getAttribute(‘属性’) 获取自定义的属性值
<body>
<div id="demo" index="1" class="nav"></div>
</body>
<script>
var div = document.querySelector("div")
console.log(div.id)
console.log(div.getAttribute('id'))
console.log(div.getAttribute('index'))
</script>
设置属性值
-
element.属性 = ‘值’ 设置内置属性值
-
element.setAttribute(‘属性’,‘值’)
var div = document.querySelector("div") div.setAttribute('class','hello') div.setAttribute('index',2)
移出属性
-
element.removeAttribute(‘属性’)
div.removeAttribute('index')
计数器案例
<script>
var btn = document.querySelector("button");
var flag = 0
btn.onclick = function () {
if (flag == 0) {
document.body.style.background = '#000'
flag = 1
} else if (flag == 1) {
document.body.style.background = '#fff'
flag = 0
}
}
</script>
全选与反选案例
<script>
var all = document.querySelector('.all');
var box = document.querySelectorAll('tbody input');
//全选
all.onclick = function(){
//设置点击事件
for(var i = 0; i < box.length; i++){
box[i].checked = this.checked
//循环,为每一个 input 设置选中属性
}
}
//反选
for(var i = 0; i < box.length; i++){
//循环出所有的 input 标签
box[i].onclick = function(){
//设置点击事件,当点击一个 input 时 判断其他 input 标签状态
var flag = 1;
//设置旗帜变量,如果为 1 则反选
for(var i = 0; i < box.length; i++){
if(!box[i].checked){
//如果 tbody 中的 input 有一个没有被选中,执行判断语句
flag = 0;
break;
}
}
all.checked=flag //结果
}
}
</script>
nav案例
<script>
var lis = document.querySelectorAll('li');
//获取全部 li 标签
var divs = document.querySelectorAll('div');
//获取全部 div 标签
for (var i = 0; i < lis.length; i++) {
//循环 li 标签
lis[i].setAttribute('index', i);
//为每一个 li 标签设置 index 属性
lis[i].onclick = function () {
//设置点击事件
for (var i = 0; i < lis.length; i++) {
//清除所有样式
lis[i].className = ''
}
this.className = 'active';
//设置点击样式
var index = this.getAttribute('index');
//获取 index 属性
for(var i = 0; i<divs.length; i++){
//循环 div 标签
divs[i].style.display = 'none';
//设置所有 div 隐藏
}
divs[index].style.display = 'block';
//设置索引值为 index 的 div 的样式为 显示
}
}
</script>
节点操作
网页中所有的内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node来表示。
一般的,节点至少拥有nodeName(节点名称)、 node Type(节点类型)、nodeValue(节点值)
常用节点分为四类:
- 文档节点:整个html文档 9 null
元素节点:html文档中的html标签 1 null
属性节点:元素的属性 2 属性值
文本节点:html标签中的文本内容 3 文本内容
父子节点
父节点
node.parenNode
- parentNode属性可返回某节点的最近一个父节点
- 如果指定的节点没有父节点则返回null
<body>
<div class='father'>
我是爸爸
<div id= 'son'>我是儿子</div>
</div>
</body>
</html>
<script>
var son = document.getElementById('son')
console.log(son.parentNode)
</script>
子节点
所有子节点
parentNode.childNodes (标准)
parentNode.childNodes返回包含指定节点的子节点的集合——不提倡使用
子元素节点
parenNode.children(非标准)
parentNote.children只是一个只读属性,返回所有的子元素的节点。它只返回子元素节点,其余节点不返回——掌握
<body>
<div>
我是爷爷
<div class='father'>
我是爸爸
<div id= 'son'>我是大儿子</div>
<div>我是小儿子</div>
</div>
</div>
</body>
</html>
<script>
var son = document.getElementById('son')
var father = document.querySelector('.father')
console.log( father.children )
</script>
第一个子节点
parentNode.firstChild
firstChild返回第一个子节点,找不到则返回null。
最后一个子节点
parentNode.lastChild
lastChild返回最后一个子节点,找不到则返回null
第一个子元素节点
parentNode.firstElementChild
返回第一个子元素节点,找不到则返回null
最后一个子元素节点
parentNode.lastElementChild
返回最后一个子元素节点,找不到则返回null
**注意:**以上两种方法有兼容性问题 IE9 以上才支持,实际开发中,firstChild和lastChild包含其他节点,操作不方便,而firstElementChild和lastElementChild又有兼容性问题。
解决方法:
- 如果想要第一个子元素节点,可以使用parentNode.children[0]
- 如果想要最后一个子元素节点可以使用parenNode.children[parentNode.children.length-1]
<script>
var ul = document.querySelector('ul')
//firstChild 第一个子节点
console.log(ul.firstChild)
console.log(ul.lastChild)
//firstElementChild 返回第一个子元素节点
console.log(ul.firstElementChild)
console.log(ul.lastElementChild)
//实际开发的写法 既没有兼容性问题又返回第一个元素
console.log(ul.children[0])
console.log(ul.children[ul.children.length-1])
</script>
兄弟节点
下一个兄弟节点
node.nextSibling
上一个兄弟节点
node.previousSibling
<div class='a'>哥哥</div>
<div class="b">弟弟</div>
<script>
var a =document.querySelector('.a')
var b =document.querySelector('.b')
console.log(a.nextSibling)
console.log(b.nextSibling)
</script>
下一个兄第元素节点(IE9以上支持)
node.nextElementSibling
上一个兄弟元素节点(IE9以上支持)
node.previousElementSibling
<div class='a'>哥哥</div>
<div class="b">弟弟</div>
<script>
var a =document.querySelector('.a')
var b =document.querySelector('.b')
console.log(a.nextElementSibling)
console.log(b.previousElementSibling)
</script>
创建节点
document.createElement(‘tagName’) 动态创建元素节点
添加节点
node.appendChild(Child)
将一个节点添加到指定父节点的子节点列表末尾。
node.insertBefore(child,指定元素)
将一个节点添加到指定父节点的子节点列表的前面
<ul>
<li>子节点</li>
</ul>
<script>
var ul =document.querySelector('ul')
var li = document.createElement('li')
li.innerHTML = '添加的子节点'
ul.appendChild(li)
var li2 = document.createElement('li')
li2.innerHTML = '添加的子节点'
ul.insertBefore(li2,ul.children[0])
</script>
ELement.insertAdjacentElement()方法的使用(十分推荐)
Element.insertAdjecentElement方法解析HTML字符串,然后将生成的节点插入DOM树的指定位置
-
beforebegin——在当前元素节点的前面
-
afterbegin——在当前元素节点的里面,插在它的第一个子元素之前
-
beforeend——在当前元素节点的里面,插在他的最后一个子元素之后
-
afterend——在当前元素节点的后面
//beforebegin
var box = document.querySelector('.box')
box.insertAdjacentElement('beforebegin','<p>我是第三者</p>')
//afterbegin
var box = document.querySelector('.box')
box.insertAdjacentElement('afterbegin','<p>我是第三者</p>')
//beforeend
var box = document.querySelector('.box')
box.insertAdjacentElement('beforeend','<p>我是第三者</p>')
//afterend
var box = document.querySelector('.box')
box.insertAdjacenElement('afterend','<p>我是第三者</p>')
删除操作
node.removeChild(child)
从node节点中删除一个子节点,返回删除的节点
<script>
var ul =document.querySelector('ul')
var li = document.createElement('li')
li.innerHTML = '添加的子节点'
ul.appendChild(li)
var li2 = document.createElement('li')
li2.innerHTML = '添加的子节点'
ul.insertBefore(li2,ul.children[0])
ul.removeChild(ul.children[0])
</script>
复制节点
node.cloneNode
返回调用该方法的节点的一个副本
注意:
- 如果括号参数为空或者为flase,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
- 如果括号参数为True,则是深度拷贝,会复制节点本身
<ul>
<li>子节点</li>
</ul>
<script>
var ul =document.querySelector('ul')
var clone = ul.cloneNode(true)//flase为不复制子元素
console.log(clone)
</script>
高级事件
注册事件(两种方式)
给元素添加事件,称为 注册事件 或者 绑定事件。
注册事件有两种方式: 传统方式 和 监听注册方式
传统注册方式
- 利用 on 开头的事件 onclick
- btn.onclick = function(){}
- 特点:注册事件的唯一性
- 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
监听注册方式
- w3c 标准 推荐方式
- addEventListener()他是一个方法、
- IE9 之前的 IE不支持此方法,可使用 attachEvent()代替
- 特点:同一个元素同一个事件可以注册多个监听器
- 按注册顺序依次执行
事件监听
eventTarget.addEventListener(type,listener[,useCapture])
将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数
- type:事件类型,如:click、mousemover
- listener:事件处理函数,事件发生时,会调用该监听事件
- useCapture:可选参数,书一个布尔值,默认时flse。
删除事件(解绑事件)
传统注册方式
eventTarget.onclick = null;
监听注册方式
- eventTarget.removeEventListener (type , listener[ , useCapture]);
- eventTarget.detachEvent(eventNameWithon, callback)
DOM事件流
事件流 描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照待定的顺序传播,这个传播过程即DOM事件流
- 事件冒泡:事件开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程
- 事件捕获:由DOM最顶层节点开始,然后逐级向下传播到DOM最底层元素的接收过程
DOM事件流会经历3个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
注意:
- js代码中只能执行捕获或者冒泡其中一个阶段
- onclick 和 attachEvent 只能得到冒泡阶段
- addEventListener(type,listenes[, useCapture])第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;如果是flase(默认),表示在事件冒泡阶段处理程序
- 有些事件没有冒泡,如:onblur,onfocus,onmouseenter、onmouseleave
事件冒泡
<body>
<div class="father">
<div class="son">儿子</div>
</div>
</body>
</html>
<script>
//son => father => body=> html => document
var son = document.querySelector('.son')
son.addEventListener('click',function(){
alert('我是儿子')
})
var father = document.querySelector('.father')
father.addEventListener('click',function(){
alert('我是爸爸')
})
document.addEventListener('click',function(){
alert('我是爷爷')
})
</script>
事件捕获
<body>
<div class="father">
<div class="son">儿子</div>
</div>
</body>
</html>
<script>
// document => body => html => father => son
var son = document.querySelector('.son')
son.addEventListener('click',function(){
alert('我是儿子')
},true)
var father = document.querySelector('.father')
father.addEventListener('click',function(){
alert('我是爸爸')
},true)
document.addEventListener('click',function(){
alert('我是爷爷')
},true)
</script>
事件对象
事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象。
- 誰绑定了这个事件
- 鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置
- 键盘触发事件的话,会得到键盘的相关信息,如按了哪个键。
eventTarget.addEventListenter(‘click’,function(e){ })
事件对象的属性和方法
事件对象属性方法 | 说明 |
---|---|
e.target | 返回触发事件的对象 |
e.srcElement | 返回触发事件的对象(非标准 IE6~8使用) |
e.type | 返回事件的类型 如click mouseover |
e.cancelBubble | 阻止冒泡 (非标准 IE6~8使用) |
e.returnValue | 阻止默认事件(非标准 IE6~8使用) |
e.preventDefault() | 阻止默认事件 |
e.stopPropagation() | 阻止冒泡 |
设置自定义属性
设置自定义属性 - data-名称
获取自定义属性 - .dataset.名称
e.target 和 this的区别
- this是事件绑定的元素(绑定这个事件处理函数的元素)
- e.target是事件触发的元素
常情况下terget 和 this是一致的, 但有一种情况不同,那就是在事件冒泡时(父子元素有相同事件,单击子元素,父元素的事件处理函数 也会被触发执行), 这时候this指向的是父元素,因为它是绑定事件的元素对象, 而target指向的是子元素,因为他是触发事件的那个具体元素对象。
<body>
<ul>
<li>1</li>
<li>1</li>
<li>1</li>
</ul>
</body>
</html>
<script>
var ul = document.querySelector('ul')
ul.addEventListener('click',function(e){
console.log(e.target)
console.log(this)
})
</script>
------------------------------------ |
| e.target | 返回触发事件的对象 |
| e.srcElement | 返回触发事件的对象(非标准 IE6~8使用) |
| e.type | 返回事件的类型 如click mouseover |
| e.cancelBubble | 阻止冒泡 (非标准 IE6~8使用) |
| e.returnValue | 阻止默认事件(非标准 IE6~8使用) |
| e.preventDefault() | 阻止默认事件 |
| e.stopPropagation() | 阻止冒泡 |
设置自定义属性
设置自定义属性 - data-名称
获取自定义属性 - .dataset.名称
e.target 和 this的区别
- this是事件绑定的元素(绑定这个事件处理函数的元素)
- e.target是事件触发的元素
常情况下terget 和 this是一致的, 但有一种情况不同,那就是在事件冒泡时(父子元素有相同事件,单击子元素,父元素的事件处理函数 也会被触发执行), 这时候this指向的是父元素,因为它是绑定事件的元素对象, 而target指向的是子元素,因为他是触发事件的那个具体元素对象。
<body>
<ul>
<li>1</li>
<li>1</li>
<li>1</li>
</ul>
</body>
</html>
<script>
var ul = document.querySelector('ul')
ul.addEventListener('click',function(e){
console.log(e.target)
console.log(this)
})
</script>