1.事件概述
1.1 什么是事件
事件是可以被 JS 检测到的行为,实质上是一种交互操作。
例如:我们可以给某按钮添加一个 onclick
(点击)事件,当用户点击时触发某个函数。
1.2 事件的作用
- 各个元素之间可以借助事件来进行交互
- 用户和页面之间也可以通过事件来交互
- 后端和页面之间也可以通过事件来交互(减轻服务器压力)
注意:事件通常会与函数进行配合,当事件发生了函数才会执行,事件的本质就是一次交互操作。
1.3 事件传递
JS 中规定:
事件不仅能够和触发者交互,还会在特定情况下沿着 dom tree 逐级传递,和 dom tree 中的各个节点进行交互。而 JS 中的这种机制被称为事件传递机制。
事件交互的两种方式:
- 事件冒泡:
事件从最具体的元素开始,沿着 DOM 树逐级向上依次触发,直至最不具体的元素停止。
因为<div> <button>点我</button> </div> var div = document.querySelector("div"); var button = document.querySelector("button"); button.onclick = function() { alert("按钮被点击了!"); } div.onclick = function() { alert("div 被点击了!"); }
div
包含了button
,所以button
在 DOM 树中是div
的子节点,所以点击按钮会向上冒泡,先是button
触发了事件,紧接着是div
触发了事件。 - 事件捕获:
事件从最不具体的元素开始,沿着 DOM 树逐级向下依次触发,直至最具体的元素停止。
将第三个参数设置为<div> <button>点我</button> </div> var div = document.querySelector("div"); var button = document.querySelector("button"); div.addEventListener("click", function() { alert("div 被点击了"); }, true); button.addEventListener("click", function() { alert("button 被点击了"); }, true);
true
,这样点击button
时就会触发事件捕获,先是div
触发事件,紧接着button
触发事件。
由图可知捕获过程要先于冒泡过程。
W3C 规定:事件冒泡 + 事件捕获 + 事件真正的触发者等各个分支构成了 JS 的事件机制。
注意:如果没有特殊情况,均采用事件冒泡。
2.非 IE 浏览器中的 事件绑定
2.1 HTML 事件
绑定操作发生在 HTML 代码中的事件,称为 HTML 事件。
语法:
on + 事件 = 函数();函数();函数();...
例如:
<div class="d1" onclick="test1();test2()">
<div class="d2" onclick="test2()"></div>
</div>
var div1 = document.querySelector(".div1");
var div2 = document.querySelector(".div2");
function test1() {
console.log("这是第一个函数");
}
function test2() {
console.log("这是第二个函数");
}
在上述 HTML 代码中,分别给 d1 和 d2 绑定了效果不同的 HTML 事件。
注意:
- HTML 事件采用冒泡机制来处理事件。即 点击 d2 时会先执行 d2 的绑定事件(test2()函数),然后采用事件冒泡将事件传递给上一级 DOM 节点(d1),然后 d1 执行自己的绑定事件。
- 函数执行的顺序按照绑定事件时函数的顺序为准。
2.1.1 移除 HTML 事件的方式
语法:
元素.setAttribute("on+事件名", null);
例如:
button.setAttribute("onclick", null);
2.1.2 HTML 事件的缺陷
- 耦合性太强,修改一处另一处也要修改。
- 当函数没有加载成功时,用户去触发事件就会报错。
2.2 DOM 0级事件
在 JS 脚本中,直接通过 on+事件名
方式绑定的事件称为是 DOM0 级事件。
语法:
元素.on+事件名 = function() {需要执行的语句}
例如:
button.onclick = function() {
console.log("按钮被点击了");
}
注意:以冒泡机制来处理事件,不存在兼容问题。
2.2.1 DOM0 级事件移除方式
语法:
元素.on+事件名 = null;
例如:
button.onclick = null;
2.2.2 DOM0 级事件的缺陷
一次只能绑定一个触发函数,如果同时绑定多个触发函数,则以最后一个为准。
2.3 DOM 2级事件
在 JS 脚本中,通过 addEventListener
函数绑定的事件被称为 DOM2级事件。
语法:
元素.addEventListener(type, listener, useCapture);
- type:事件类型(没有
on
) - listener:监听函数,绑定的函数
- useCapture:是否使用捕获机制。如果不写,默认值为
false
。
注意:DOM2 级事件可以绑定多个函数,执行顺序按照函数熟悉的顺序。
例如:
var button = document.querySelector("button");
button.addEventListener("click", function() {
console.log(11);
}, true);
button.addEventListener("click", function() {
console.log(22);
}, true);
上述代码表示给按钮添加了两个 DOM2 级点击事件,事件传递采用事件捕获的方式。
2.3.1 DOM2 级事件移除方式
语法:
node.removeEventListener(type, 外部函数名, useCapture);
例如:
var button = document.querySelector("button");
button.addEventListener("click", clickEvent, false);
button.removeEventListener("click", clickEvent, false);
function clickEvent() {
console.log(22);
}
注意:DOM2 级事件中如果绑定函数为匿名函数则无法解除。能够删除的只能是外部函数,并且移除时的参数要与添加时的参数完全一致。
3.IE 浏览器中的 事件绑定
HTML 事件处理程序 等同于非 IE
DOM0 级事件 等同于非 IE
-
DOM2 级事件
在 JS 脚本中,通过attachEvent
函数绑定事件
语法:元素.attachEvent(type, listener);
- type:事件类型(有
on
) - listener:监听函数,绑定的函数
注意:如果绑定多个函数,按照函数书写的倒序执行。
例如:
var div1 = document.querySelector(".d1"); var div2 = document.querySelector(".d2"); div1.attachEvent("onclick", test1); div2.attachEvent("onclick", test1);
不支持 IE11。
- type:事件类型(有
3.1 移除 DOM2 级事件
语法:
元素.detachEvent(type, listener);
例如
div1.detachEvent("onclick", test1);
div2.detachEvent("onclick", test1);
4.解决浏览器中事件绑定的兼容性问题
由于 IE 浏览器的事件绑定和 非 IE 浏览器的事件绑定方式方法都有所不同,所以单一的某种函数都不能完美解决不同浏览器下的方法绑定问题。
那么我们又应该如何面对在不同浏览器下 事件绑定 这个问题呢?
4.1 解决方案的思路
- 绑定事件时:
如果能使用addEventListener
方法绑定的,就采用本方法,否则使用attachEvent
方法绑定。 - 解绑事件时:
如果能采用addEventListener
方法绑定的,就使用removeEventListener
方法解绑,否则采用detachEvent
方法解绑。
var div = document.querySelector("div");
var superEvent = {
// 添加事件的兼容性函数
add: function addEvent(ele, type, func) {
if (ele.addEventListener) { // 判断在哪个环境下
ele.addEventListener(type, func);
} else {
ele.attachEvent("on" + type, func);
}
},
// 移除事件的兼容性函数
remove: function removeEvent(ele, type, func) {
if (ele.addEventListener) { // 判断在哪个环境下
ele.removeEventListener(type, func);
} else {
ele.detachEvent("on" + type, func);
}
}
};
function func() {
console.log(11);
}
superEvent.add(div, "click", func);
superEvent.remove(div, "click", func)
5.鼠标事件
语法:
元素.on+鼠标事件名 = 调用函数
例如:
diiv.ondbclick = function() {
console.log("这是 div");
}
注意:
- DOM0 级事件可以给一个元素绑定多个不同类型的事件。
- 事件之间互不影响。
- 默认是冒泡事件。
5.1 click 单击时触发
var div = document.querySelector("div");
// 单击事件
div.onclick = function() {
console.log("div 被点击了");
}
5.2 dbclick 双击时触发
// 双击事件
div.ondblclick = function() {
console.log("div 被双击了");
}
5.3 mousedown 按下时触发
// 鼠标按下事件
div.onmousedown = function() {
console.log("鼠标按下了");
}`
5.4 mouseup 抬起时触发
// 鼠标抬起事件
div.onmouseup = function() {
console.log("鼠标抬起了");
}
5.5 mousemove 移动时触发
// 鼠标在 div 中移动了
div.onmousemove = function() {
console.log("鼠标在 div 中移动了");
}
5.6 mouseenter(不冒泡)移入时触发
div2.onmouseenter = function() {
console.log("鼠标移入了div2 中")
}
5.7 mouseleave(不冒泡)移出时触发
div2.onmouseleave = function() {
console.log("鼠标移出了 div2 ")
}
5.8 mouseover(冒泡)移入时触发
div1.onmouseover = function () {
console.log("鼠标移入了 div1 中")
}
5.9 mouseout(冒泡)移出时触发
div1.onmouseout = function () {
console.log("鼠标移出了 div1 ")
}
5.10 鼠标事件总结
- 鼠标的基本事件默认采用冒泡传递
- 可以给一个元素添加多个不同的鼠标事件,不同的鼠标事件之间互不影响。
-
mouseenter
和mouseleave
这两个事件不冒泡。
6.文档事件
文档事件中主要是指添加给整个文档的事件。在这一类事件中,绝大部分不需要用户去主动进行调用。而是通过文档的不同状态来进行自动执行。
6.1 加载成功\失败事件
- load:该事件是指节点加载成功时自动发生回调事件
- error:该事件是指节点加载失败时自动发生的回调事件
语法:
node.onload = func(){};
例如:
加载页面中的图片,如果加载成功,会回调 onload
方法,如果加载失败会回调 onerror
方法。
<img src="images/11.jpg" alt="">
<script>
document.querySelector("img").onload = function() {
console.log("图片加载成功!");
}
document.querySelector("img").onerror = function() {
console.log("图片加载失败");
}
</script>
6.2 当 DOM 加载完成时触发事件
-
DOMContentLoaded:该事件和
load
事件触发的时机不一样,先触发DOMContentLoaded
事件,后触发load
事件。DOM 文档加载步骤:
- 解析 HTML 结构
- 加载外部脚本和样式表文件
- 解析并执行脚本代码
- DOM 树构建完成 // DOMContentLoaded 执行
- 加载图片等外部文件
- 页面加载完成 // load 执行
从 DOM 文件的加载步骤可以看出,样式文件的加载会阻塞脚本的执行。
如果把内部的<script>
标签放到<link>
标签的后面,如果页面没有解析完成,那么脚本则不会触发,必须要等到样式文件加载完成之后,这种情况被称为文件阻塞。
6.3 页面(文档)发生卸载时触发的事件
- beforeunload:页面卸载时触发这个事件(页面刷新和页面关闭),通常情况下配合
event.returnValue
使用。
一般情况下都是直接添加到body
上面。而如果没有在body
上添加本事件,则需要在window
上添加。
注意:window.onbeforeunload = function() { event。returnValue = ""; return "信息已修改,是否确认离开"; }
beforeunload
事件中弹出的对话框一般情况下是不允许用户做出修改的。只能采用默认的对话框。而且在beforeunload
所关联的回调函数中也是不支持alert
弹出框的。
6.4 文档加载状态判断事件
-
readystatechange:当文档的
readyState
改变时触发这个事件(仅第二阶段)。
document
节点中拥有一个属性叫做readyState
,其拥有 3 个可能值:- loading:加载 DOM 中
- interactive:加载外部资源
- complete:加载完成
而
readystatechange
事件正是在这个状态发生改变时调用的事件。
调用的方式可以使用 DOM0 或者 DOM2 来绑定。例子:
console.log(document.readyState); // 文档加载状态变化 document.addEventListener("readystatechange", function() { console.log("文档加载状态变化" + document.readyState); }) // 文档 DOM 树加载完成 document.addEventListener("DOMContentLoaded", function() { console.log("文档 DOM 树加载完成"); }) // 页面彻底加载完成 window.onload = function() { console.log("页面彻底加载完成"); } document.querySelector("img").onload = function() { console.log("图片加载完成"); }
运行结果:
6.5 文档大小发生改变时的回调事件
-
resize:该事件是在文档大小发生改变时回调,但是因为 JS 追求变化的敏感度,将
resize
事件设置成了 0,也就是说每次文档大小发生改变都会立即调用本事件。由此造成了 一次变化,多次 resize。window.onresize = function() { console.log("clientX: " + document.documentElement.clientWidth); console.log("clientY: " + document.documentElement.clientHeight); }
解决方式:采用延迟写法来实现。
var flag = false; function frame() { if (flag) { console.log("clientWidth: " + document.documentElement.clientWidth); console.log("clientHeight: " + document.documentElement.clientHeight); } flag = false; setTimeout(function() { flag = true; }, 500); } window.onresize = function() { frame(); }
7.焦点事件
焦点:当前正在和用户发生交互的节点被称作焦点。
7.1 失去焦点事件 blur
语法:获得焦点和失去焦点事件既可以使用 DOM0 绑定也可以使用 DOM2 绑定。
var input = document.querySelector("input");
// DOM0 方式绑定
input.addEventListener("blur", function() {
console.log("输入框失去了焦点");
})
// DOM2 方式绑定
input.onblur = function() {
console.log("输入框失去了焦点");
}
7.2 获取焦点事件 focus
语法:
var input = document.querySelector("input");
// DOM0 方式绑定
input.addEventListener("focus", function() {
console.log("输入框获取了焦点");
})
// DOM2 方式绑定
input.onfocus = function() {
console.log("输入框获取了焦点");
}
注意:这两个事件均 不支持 事件冒泡(只有当前节点发生调用)。如果需要连续多次的触发,则需要使用 DOM2 级绑定事件中的捕获事件来达到。
8.文档滚动事件
scroll
事件会在 文档 或 元素 发生滚动时触发
文档发生滚动时:
属性 scrollTop\scrollLeft
表示文档滚动的距离(没有单位)
- IE:
document.documentElement.scrollTop\Left
- 非 IE:
document.body.scrollTop\Left
可以使用 document.body.scrollTop || document.documentElement.scrollTop
来解决兼容性。
例如:
var button = document.querySelector("button");
button.onclick = function() {
document.body.scrollTop = 1000;
document.documentElement.scrollTop = 1000;
}
document.onscroll = function() {
// 滚动事件调用一次就输出一次滚动距离
console.log(document.body.scrollTop || document.documentElement.scrollTop);
}
9.元素滚动事件
元素发生滚动时并不存在兼容性的问题,但是需要有一个前提:必须存在滚动条(元素的滚动条属性可以通过 overflow: scroll / overflow-x: scroll / overflow-y: scroll
来实现)。
当元素发生滚动时,可以通过 元素.scrollTop / scrollLeft
获取到元素的位移距离。
例如:
<style>
div {
overflow: scroll;
width: 100px;
height: 100px;
background-color: skyblue;
}
</style>
<script>
var div = document.querySelector("div");
div.onscroll = function() {
console.log("top " + div.scrollTop + " left" + div.scrollLeft);
}
</script>
注意:內容要占满 div
的空间。
10.键盘事件
10.1 键盘事件种类
键盘事件是指当用户在操作键盘的时候会被自动触发的事件,通常有以下三种:
- keydown:用户按下任意键都可以触发这个事件。如果按住不放,事件会被连续触发
- keypress:用户按下任意键都可以触发这个事件(功能键除外)。如果按住不放,事件会被连续触发。
- keyup:用户释放按键时触发。
// keydown 事件
var input = document.querySelector("input");
input.onkeydown = function() {
console.log("键盘被按下了");
}
// keypress 事件
input.onkeypress = function() {
console.log("键盘被按下了");
}
// keyup 事件
input.onkeyup = function() {
console.log("按键被松开了");
}
注意:键盘事件一般绑定在需要用户输入的元素上(例如:input),但是由于键盘事件默认采用冒泡机制,因此将键盘事件直接绑定在 body
之上也是允许的。
10.2 键盘事件中提供的属性
在键盘事件中可以通过 event.keycode
来获取按下的按键的编码值。
例如:
// 该方式不区分大小写
input.onkeydown = function() {
console.log("down " + event.keyCode);
}
// 该方式区分大小写
input.onkeypress = function() {
console.log("down " + event.keyCode);
}
10.3 对比 keydown 和 keypress 事件
-
keypress
主要用来捕获 数字(包括 shift + 数字的符号)、字母(包括大小写)、先键盘等能够显示在屏幕中的字符。但是不能对系统功能键(例如:退格)进行正常的响应。
而keydown
和keyup
通常可以捕获键盘除了 PrScrn 之外所有按键(这里不讨论特殊键盘的特殊键)。 - 捕获字符长度有区别
·keypress
只能捕获单个字符。
keydown
和keyup
可以捕获组合键。 - 捕获字符大小写识别区别
keypress
可以捕获单个字符的大小写。
keydown
和keyup
对于单个字符捕获的keyCode
都是一个值,也就不能判断单个字符的大小写。 - 捕获字符数字区别
keypress
不区分小键盘和主键盘的数字字符。
keydown
和keyup
区分小键盘和主键盘的数字字符。 -
特殊情况
- PrScrn 按键的
keypress
、keydown
和keyup
都不能捕获。 - 上下左右等功能键的
keydown
、keyup
都能获取keyCode
,并且值相等。
- PrScrn 按键的
常见的键盘按键编码:
11.触摸事件
11.1 手机触摸事件
- touchstart:当手指触摸屏幕时触发,即使有一个手指放在屏幕上也会触发。
- touchmove:当手指在屏幕上滑动时连续触发。
- touchend:当手指在屏幕上移开时触发。
- touchcancel:当系统停止跟踪触摸时触发。(如电话接入或弹出信息,一般在这个操作中来做一些暂停游戏类的操作)。
例如:
var div = document.querySelector("div");
div.addEventListener("touchstart", function() {
console.log("touch begin");
})
div.addEventListener("touchmove", function() {
console.log("touch move");
})
div.addEventListener("touchend", function() {
console.log("touch end");
})
div.addEventListener("touchcancel", function() {
console.log("touch cancel");
})
注意:
- 除非特殊说明,否则事件均为冒泡事件。
- 手机触摸事件必须使用 dom2 来进行绑定。
- 可以给一个元素添加多个触摸事件。
11.2 事件对象的属性
事件对象:即 事件触发时 用来保存 事件相关的所有信息的对象。
注意:事件对象基本都是系统为我们自动生成的,不必手动创建。
div.addEventListener("touchstart", function() {
console.log(event);
})
- touches:表示当前跟踪的触摸操作的
Touch
对象的数组(当前屏幕上所有的触摸点列表)。-
触摸对象,即 事件对象的
touches
属性 中的每一个元素。一次触摸会创建一个触摸对象。
触摸对象中提供了很多属性方便我们获取和使用:- clientX:触摸目标在视口中的 X 坐标。
- clientY:触摸目标在视口中的 Y 坐标。
- identifier:表示触摸的唯一 id。
- pageX:触摸目标在页面中的 x 坐标。
- pageY:触摸目标在页面中的 y 坐标。
- screenX:触摸目标在屏幕中的 x 坐标。
- screenY:触摸目标在屏幕中的 y 坐标。
- target:触摸的 DOM 节点坐标。
通常都会在触摸事件被触发的时候,通过这两个属性获取当前节点的位置。
-
- targetTouches:特定于事件目标的
Touch
对象的数组(当前对象上所有的触摸点列表)。 - changeTouches:表示自上次触摸以来发生了什么改变的
Touche
对象数组(涉及当前事件的触摸点列表)。
12.this 对象
this 代表 函数运行时 自动生成的 一个 用来指代函数调用者 的对象,
this
只能在函数内部使用。
例子:
var div = document.querySelector("div");
function test() {
console.log(this);
}
test(); // 指向 window
document.addEventListener("click", test); // 指向 document
div.addEventListener("click", test); // 指向 div
根本原则:谁是调用者,this
就指向谁。
13.HTML event 事件应用
13.1 非 IE 下的 event 对象
13.1.1 event 对象及获取 event 对象的方法
当 DOM tree 中某个事件被触发的时候,会同时自动产生一个用来描述事件所有的相关信息(比如发出事件的元素、或者是事件的类型)的对象,这个对象就是 event
(事件对象)。
获取方式:
- 直接通过
event
获取 - 通过函数传参数的形式来使用,一般而言我们使用 形参
e
或者eve
来代替。var div = document.querySelector(".d1"); // div.onclick = function(e) { // console.log(e); // }; // div.onmouseenter = function(eve) { // console.log(eve); // } div.onclick = function() { console.log(event); }
13.1.2 event 中常用的属性和方法
因为 event
对象是用来描述 发生的事件的信息 的,而 event
对象当中所提供的一系列属性和方法正是用来获取这些信息的途径。
-
type 属性
type 属性用来获得 当前触发事件 的类型,此属性只读。var div = document.querySelector(".d1"); div.onclick = function(e) { console.log(e.type); // 依赖于事件触发而存在,是只读属性 };
-
bubbles 属性
bubbles 属性用来获得 当前触发事件 的类型是否冒泡。如果冒泡则返回true
,否则返回false
。div.onmouseenter = function(eve) { console.log(eve.bubbles); }
-
stopPropagation()
该方法用于阻止事件从当前节点传播到下一个节点。
语法:event.stopPropagation();
例如:
var div = document.querySelector(".d1"); div.onclick = function(e) { // 阻止事件的传播 e.stopPropagation(); }; document.body.onclick = function() { // 如果不添加 stopPropagation() 将会被打印 console.log("body 受到监听"); }
注意:该方法只是阻止了事件的传播,但是并不会影响同一节点上的其它句柄。
-
preventDefault()
event
对象中提供了一个名为preventDefault
的方法,用来取消当前节点的默认行为(例如超链接的点击跳转行为),该方法没有返回值。语法:
<a href="http://www.baidu.com">百度</a> <script> var aLink = document.querySelector("a"); aLink.onclick = function() { event.preventDefault(); // 添加后不会跳转 } </script>
-
cancelable()
event
对象中提供了一个名为cancelable
的属性,用来判断当前节点能否使用preventDefault()
来取消默认行为,如果可以则返回true
,否则会返回false
。var aLink = document.querySelector("a"); aLink.onclick = function() { console.log(event.cancelable); }
13.2 非 IE 下的 event 对象属性
13.2.1 eventPhase 属性
eventPhase:事件传导至 当前节点 时处于什么状态。
- 1:事件处于捕获状态
- 2:事件处于真正的触发者
- 3:事件处于冒泡状态
注意:该返回值是 只读 状态。
事件捕获:
var div = document.querySelector("div");
var span = document.querySelector("span");
span.addEventListener("click", function() {
console.log("span: " + event.eventPhase);
})
div.addEventListener("click", function() {
console.log("div: " + event.eventPhase);
}, true);
document.body.addEventListener("click", function() {
console.log("body: " + event.eventPhase);
}, true);
document.addEventListener("click", function() {
console.log("document: " + event.eventPhase);
}, true);
事件冒泡:
var div = document.querySelector("div");
div.addEventListener("click", function() {
console.log("div: " + event.eventPhase);
});
document.body.addEventListener("click", function() {
console.log("body: " + event.eventPhase);
});
document.addEventListener("click", function() {
console.log("document: " + event.eventPhase);
});
13.2.2 target 属性与 currentTarget 属性
- target:返回事件真正的触发者,和
this
基本相同,只不过this
返回的是调用者。 - currentTarget:返回事件的监听者(触发的事件绑定到了哪个节点,就返回谁)。
例如:
<div class="d1">
d1
<div class="d2">d2</div>
</div>
<script>
var d1 = document.querySelector(".d1");
d1.onclick = function() {
console.log(event.target);
console.log(event.currentTarget);
}
</script>
13.3 IE 中的 event 对象
13.3.1 IE 中的 event 对象与非 IE 下的区别
- 非 IE 下
event
的值默认为undefined
,而 IE中event
的值默认为null
。 - 非 IE 下可以随意通过 DOM0 或 DOM2 中的参数来使用
event
,而 IE 中 DOM0 无法使用传参的方式来使用event
。
注意:因为 event
本身是归属于 window
的一个属性,因此我们可以在函数中通过 var eve = e || window.event
来解决获取 event
的兼容性问题。
13.3.2 IE 中的 event 对象的常用属性和方法
由于 IE 下存在某些属性的赋值方式和非 IE 中略有不同,因此在这里单独说明一下。
- secElement
srcElement
属性代表事件真正的触发者,等同于非 IE 下的target
属性。
因此,为了在不同的浏览器下解决获取target
的兼容性问题,可以采取如下写法:var target = event.target || eve.srcElement;
- cancelBubble
cancelBubble
属性用来阻止事件在当前节点上的冒泡行为。
作用类似于非 IE 下的stopPropagation()
。
语法:
注意:event.cancelBubble = true;// 可取消冒泡 event.cancelBubble = false; // 默认值
stopPropagation()
方法用于阻止事件传递,而cancelBubble
属性则仅阻断事件冒泡。 - returnValue
returnValue
属性用来设置 书否取消当前节点的默认行为。
作用类似非 IE 下的proventDefault()
。
语法:e.returnValue = false; // 取消默认行为 e.returnValue = true; // 默认值
14.事件委托
事件委托是给父元素绑定事件,用来监听子元素的冒泡事件,并能找到是哪个子元素的事件。
例子:
<ul>
<li>li 1</li>
<li>li 2</li>
<li>li 3</li>
<li>li 4</li>
</ul>
var ul = document.querySelector("ul");
ul.onclick = function() { // 为父元素绑定事件,监听子元素的冒泡
console.log(event.target.innerHTML);
}
15.三级联动
-
select
元素的option
创建方式var option = new Option("显示的內容");
-
select
元素添加option
元素,select.options.add(新建的 option);
-
select
元素清空option
的方式:select.options.length = 0;
-
select
元素改变时触发的事件:select.onchange = function() {}
-
select
元素当前正选中的option
序号select.selectedIndex
,序号从 0 开始。
例子(不完整):
<span>省:</span>
<select id="province">
<option>-请选择-</option>
</select>
<span>市:</span>
<select id="city">
<option>-请选择-</option>
</select>
<span>区:</span>
<select id="district">
<option>-请选择-</option>
</select>
<script>
var province = document.querySelector("#province");
var city = document.querySelector("#city");
var district = document.querySelector("#district");
var provinceIndex = 0;
// var option = new Option("山西省");
// province.options.add(option);
var provinceArr = ["山西省", "辽宁省", "福建省"];
var cityArr = [
["太原市", "临汾市", "大同市", "运城市", "长治市"],
["沈阳市", "大连市", "鞍山市", "阜新市"],
["福州市", "厦门市", "三明市", "莆田市", "泉州市", "龙岩市"]
];
var districtArr = [
[["太原 1 区", "太原 2 区", "太原 3 区"], ["临汾 1 区", "临汾 2 区", "临汾 3 区"], ["大同 1 区", "大同 2 区"]],
[["沈阳 1 区", "沈阳 2 区"], ["大连 1 区", "大连 2 区"]],
[["福州 1 区", "福州 2 区",], ["厦门 1 区", "厦门 2 区"]]
];
for (var i = 0; i < provinceArr.length; i++) {
var provinceOpt = new Option(provinceArr[i]);
province.options.add(provinceOpt);
}
province.onchange = function(eve) {
provinceIndex = eve.target.selectedIndex - 1;
if (provinceIndex == -1) {
city.options.length = 0;
district.options.length = 0;
} else {
city.options.length = 0;
// 根据省的序号加载市的內容
for (var i = 0; i < cityArr[provinceIndex].length; i++) {
var cityOpt = new Option(cityArr[provinceIndex][i]);
city.options.add(cityOpt);
}
// 加载所选省的市的第一个区(默认)
district.options.length = 0;
for (var i = 0; i < districtArr[provinceIndex][0].length; i++) {
var districtOpt = new Option(districtArr[provinceIndex][0][i]);
district.options.add(districtOpt);
}
}
}
city.onchange = function(eve) {
var cityIndex = eve.target.selectedIndex;
district.options.length = 0;
for (var i = 0; i < cityArr[cityIndex].length; i++) {
var districtOpt = new Option(districtArr[provinceIndex][cityIndex][i]);
district.options.add(districtOpt);
}
}
</script>