一.事件处理
1.基本概念
(1)事件:JavaScript可以侦测到的行为(用户在页面上进行的某种操作)
页面加载(浏览器打开页面)、单击鼠标、鼠标进入某个区域、焦点、键盘
(2)事件处理程序:用户进行某种操作以后所运行的JavaScript程序段
(3)事件驱动式:当事件发生后才去执行相应的程序
(4)事件流:事件发生时,会在发生事件的元素节点与DOM树根节点之间按照特定的顺序进行传播,这个事件传播的过程就是事件流。
(5)在web中对事件流的解决方案:
a.事件捕获:网景公司Netscape。事件流传播顺序应该是从DOM树的根节点到发生事件的元素节点
b.事件冒泡:微软公司。事件流传播的顺序应该是从发生事件的元素节点到DOM树的根节点
冒泡的前提是:父级也定义了相应的事件。当子元素与父元素有相同的事件时,当子元素被触发时父元素也会被触发冒泡机制
c.W3C的事件流处理:在事件发生阶段采用捕获方式(此时不处理),在时间处理阶段采用冒泡
(6)事件捕获的实现:
addEventListener(事件名,事件处理程序,事件处理方式)
事件名:click、change、load、mousedown...
事件处理方式:(true--表示采用事件捕获方式,false:采用事件冒泡方式)
例1:
<body>
<div id="myDiv" style="width: 100px;height:200px;background:red;">点击</div>
<script>
window.onclick = function(){
alert('window')
}
document.onclick = function(){
alert('document')
}
document.documentElement.onclick = function(){
alert('html')
}
document.body.onclick = function(){
alert('Body')
}
document.getElementById('myDiv').onclick = function(e){//e:事件对象event,只要有事件发生都会生成一个event对象
alert('myDiv')
if (window.event) {
// cancelBubble取消冒泡
window.event.cancelBubble = true //早期浏览器IE6-8
}else{
// 停止冒泡stopPropagation()
e.stopPropagation()//标准浏览器采用的方法
}
}
</script>
</body>
例2:
<style>
#parent{
width: 200px;
height: 200px;
background-color: red;
}
#child{
width: 100px;
height: 100px;
background-color: pink;
}
</style>
<body>
<div id="parent">
<div id="child"></div>
</div>
<script>
// 冒泡方式
document.getElementById('parent').addEventListener('click',function(){
alert('parent被触发')
},true)
document.getElementById('child').addEventListener('click',function(e){
alert('child被触发')
if (window.event) {
window.event.cancelBubble = true
} else {
e.stopPropagation()
}
},true)
</script>
</body>
2.事件的绑定方式:
(1)行内绑定式 <标签名 事件名=‘事件处理程序’></标签名>
(2)动态绑定式 DOM对象名.事件名 = 事件处理程序
注意:‘行内绑定式’和‘动态绑定式’的区别
异:a.‘行内绑定式’中事件名作为标签的属性,‘动态绑定式’中事件名作为DOM对象的属性
b.‘行内绑定式’的事件处理程序中的this代表的是window对象,‘动态绑定式’的事情处理程序中的this代表的是触发事件的DOM对象
同:一个DOM对象的同一个事件只能有一个事件处理程序
(3)事件监听式:可以给DOM对象的同一个事件绑定多个事件处理程序
DOM对象.addEventListener(type,callback,[capture])//标准浏览器
DOM对象.attachEvent(type,callback,[capture])//早期IE浏览器
3.删除事件绑定 DOM对象.removeEventListener(type, callback);
<body>
<button id="btn_submit">提交</button>
<button id="btn_cancel">取消</button>
<script>
let btn = document.getElementById('btn_submit')
function f1(){
alert(1)
}
btn.addEventListener('click',f1)
function f2() {
alert(2)
}
btn.addEventListener('click',f2)
function f3() {
alert(3)
}
btn.addEventListener('click',f3)
let cancel = document.getElementById('btn_cancel')
cancel.addEventListener('click',function(){
btn.removeEventListener('click',f1)//删除click事件上绑定的f1函数
btn.removeEventListener('click',f3)
})
</script>
</body>
二.事件对象
1.来源:当事件发生时,都会产生一个事件对象(event对象)
2.作用:通过事件对象可以了解与事件相关的信息(DOM对象、事件的类型...)
3.获取事件对象:
(1)早期的IE浏览器
(2)标准浏览器:将一个event对象直接传入事件处理程序中
4.常用属性:
(1)type:当前事件类型
(2)target:返回触发此事件的元素(事件的目标节点)
(3)currentTarget:返回其事件监听器触发该事件的元素
(4)bubbles:事件是否是冒泡类型
<body>
<button id="btn_test">测试事件对象</button>
<br><br>
<div id="div1" style="width: 100px;height:100px;background-color: red;"></div>
<script>
/* document.getElementById('btn_test').addEventListener('click',function(e){//e:事件对象
console.log('事件对象',e)
})
document.getElementById('div1').addEventListener('click',function(e){
console.log('事件对象',e)
}) */
/* document.getElementById('btn_test').addEventListener('click',function(e){//e:事件对象
console.log('事件类型',e.type)
})
document.getElementById('div1').addEventListener('mousemove',function(e){
console.log('事件对象',e.type)
}) */
/* document.getElementById('btn_test').addEventListener('click',function(e){//e:事件对象
console.log('事件元素',e.target)
})
document.getElementById('div1').addEventListener('mousemove',function(e){
console.log('事件元素',e.target)
}) */
document.getElementById('btn_test').addEventListener('click', function (e) {//e:事件对象
console.log('事件类型', e.currentTarget)
})
document.getElementById('div1').addEventListener('mousemove', function (e) {
console.log('事件是否冒泡', e.bubbles)
})
</script>
</body>
5.常用函数:
(1)stopPropagation():阻止事件冒泡
(2)preventDefault():阻止默认行为
<body>
<button id="btn_test">测试事件对象</button>
<br><br>
<div id="div1" style="width: 100px;height:100px;background-color: red;"></div>
<br><br>
<a href="https://www.bilibili.com" id="click_a">进入B站</a>
<script>
document.getElementById('click_a',function(e){
e.preventDefault()
})
</script>
</body>
三.事件的分类
1.页面事件
(1)load:页面加载事件。用于body内所有标签都加载完成后才触发
(2)unload:用于页面关闭时触发,经常用于清除变量,避免内存的泄露
2.焦点事件
(1)focus:当获取焦点时触发
(2)blur:失去焦点时触发
<style>
.true{
color: greenyellow;
}
.false{
color: red;
}
</style>
<body>
<div>
用户名:<input type="text" id="userName"><span id="nameInfo"></span><br>
密码:<input type="password" id="pwd"><span id="pwdInfo"></span>
</div>
<!-- 练习:表单验证 -->
<script>
// 获取用户名
let users = document.getElementById('userName')
// 失去焦点
users.addEventListener('blur',function () {
// 获取用户名后面的span
let span1 = document.getElementById('nameInfo')
if ('admin' === users.value) {
// 删除错误的类名
span1.classList.remove('false')
span1.innerHTML='用户名正确'
// 添加样式
span1.classList.add('true')
}else{
// 删除正确的类名
span1.classList.remove('true')
span1.innerHTML='请重新输入'
span1.classList.add('false')
}
})
let passwd = document.getElementById('pwd')
passwd.addEventListener('blur',function(){
let span2 = document.getElementById('pwdInfo')
if (this.value.length>=6 && this.value.length <=16 &&users.value === 'admin') {
span2.classList.remove('false')
span2.innerHTML='密码正确'
span2.classList.add('true')
}else{
span2.classList.remove('true')
span2.innerHTML='请重新输入'
span2.classList.add('false')
}
})
</script>
</body>
3.鼠标事件
(1)click:鼠标单击
(2)dblclick:鼠标双击
(3)mouseover:鼠标移入
(4)mouseout:鼠标移出
(5)change:当内容发生改变时触发--多用于input、select
<body>
<select name="" id="change">
<option value="%">请选择</option>
<option value="red">红玫瑰</option>
<option value="green">绿光</option>
<option value="pink">Hello Kitty</option>
</select>
<script>
let select = document.getElementById('change')
select.addEventListener('change',function(){
document.body.style.backgroundColor = this.value
})
</script>
</body>
(6)mousedown:当按下任意鼠标按键时触发
(7)mouseup:当释放任意鼠标按键时触发
(8)mousemove:在元素内当移动鼠标时持续触发
4.在鼠标事件中,鼠标的位置信息的获取
(1)clientX:鼠标指针位于浏览器页面当前窗口可视区的水平坐标(坐标X轴)
(2)clientY:鼠标指针位于浏览器页面当前窗口可视区的垂直坐标(Y轴坐标)
(3)pageX:鼠标指针位于文档的水平坐标(坐标X轴)
(4)pageY:鼠标指针位于文档的垂直坐标(Y轴坐标)
(5)screenX:鼠标指针位于屏幕的水平坐标(坐标X轴)
(6)screenY:鼠标指针位于屏幕的垂直坐标(Y轴坐标)
<script>
window.addEventListener('mousemove',function(e){
console.log('e.clientX:',e.clientX)
console.log('e.clientY:',e.clientY)
})
window.addEventListener('mousedown',function(e){
console.log('e.pageX:',e.pageX)
console.log('e.pageY:',e.pageY)
console.log('e.screenX:',e.screenX)
console.log('e.screenY:',e.screenY)
})
</script>
强调:事件对象的兼容性处理
(一)早期的IE浏览器版本获取事件对象的方法:window.event
标准浏览器获取事件对象的方法:event
DOM对象:addEventListener(‘事件名称’,function(e)){
let/var 变量 = e || window.event
}
(二)早期的IE浏览器对事件对象的pageX和pageY
var pageX = event.pageX || event.clientX + document.documentElement.scrollLeft;
var pageY = event.pageY || event.clientY + document. documentElement.scrollTop;
练习:当鼠标在浏览器窗口中移动时,在鼠标指针旁边显示指针的坐标
<style>
#box{
position: absolute;
}
</style>
<body>
<div id="box"></div>
<script>
window.onload = function(){
// 获取div
let div = document.getElementById('box')
// 给document绑定mousemove事件
document.onmousemove = function (event) {
let left_position = event.clientX + 'px'
let top_position = event.clientY + 'px'
div.style.left = left_position
div.style.top = top_position
div.innerHTML = left_position +',' + top_position
}
}
</script>
</body>
5.键盘事件:用户在使用键盘时触发
(1)keypress:键盘上按键按下时触发,不包含非字符按键(功能键)。保存的是按键的ASCII值
(2)keydown:键盘上按键按下时触发
(3)keyup:键盘按键弹起时触发
keydown和keyup保存的是按键的虚拟键码
<script>
document.addEventListener('keypress',function(e){
console.log('事件对象',e)
console.log('',e.keyCode)
})
document.addEventListener('keydown',function(e){
// // console.log(e.keyCode)
// // if (e.altKey) {
// // alert('Alt')
// // }
// // if(e.ctrlKey){}
// // if (e.shiftKey) {}
// console.log(e.code)
// console.log(e.key)
})
document.addEventListener('keyup',function (e) {
console.log('keyup:',e.key)//key保存的是小写字母
console.log('keyCode:',e.keyCode)//keyCode保存的是ASCII值
})
</script>
6.表单事件:操作表单时触发
(1)submit:当表单提交时触发
(2)reset:当表单重置时触发
四.正则表达式
1.什么是正则表达式?
(1)是描述字符串组成结构的语法规则
(2)是用于匹配字符串中字符组合的模式
(3)是一个对象
2.特点
(1)非常灵活
(2)逻辑性非常强
(3)以非常简单的方式达到对字符串进行复杂的控制
3.创建正则表达式
(1)使用字面量 var 变量 = /表达式/
(2)使用RegExp构造函数 var 变量名 = RegExp(/表达式/)
或 var 变量名 = new RegExp(/表达式/)
4.正则表达式的使用
(1)test()方法:返回Boolean值。true:符合正则规则;false:不符合
正则对象.test(被验证的字符串)
(2)模式修饰符:基本语法/表达式/[switch]
switch:表示模式修饰符,是可选的,可以对正则进一步的设置
g:全局匹配 i:忽略大小写
(3)边界符:
^:表示匹配行首的文本(以...开头)
$:表示匹配行尾的文本(以...结尾)
(4)预定义字符:
.:除了'\n'之外的任意单个字符
\d:匹配0-9之间的任意数字。等价于[0-9]
\D:匹配0-9以外数字。等价于[^0-9]
\w:匹配任意字母、数字、下划线。等价于[a-zA-Z0-9]
\W:除所有字母、数字、下划线以外的字符,相当于[^a-zA-Z0-9]
\b:单词分界符
\s:匹配空格(包括换行符、空格、制表符等),相当于[\t\r\n\v\f]
match(正则表达式)方法:是string对象的方法,用来截取符合正则表达式规则的子串,返回值是数组
强调:转义字符'\',若要输出反斜杠,要使用连续两个'\\'
<script>
// var reg1 = /123/ //串长度为3
// var reg2 = RegExp(/111/)
// var reg3 = new RegExp(/222/)
// let s1 = '123'
// console.log(reg1.test(s1))
var reg = /abc/gi //全局,忽略大小写
console.log(reg.test('abc'))//true
console.log(reg.test('ABC'))//false
var reg1 = /^abc/gi
console.log(reg1.test('ABC'))//true
var reg2= /abc$/gi
console.log(reg2.test('ABC'))//true
var reg3= /^abcabc$/gi
console.log(reg2.test('AbcABc'))//true
var str = 'good idea 123 463'
var reg4 = /\s../gi //匹配空格开始两个任意单个字符
let s2 = str.match(reg4)
console.log(s2)//['id','12','46']
// 将字符串中所有的特殊字符匹配出来
var str1 = '^abc\\1.23*edf$'
var reg5 = /\.|\$|\*|\^|\\/gi
let t = str1.match(reg5)
console.log(t)// ['^','\\','.','*','$']
</script>
(5)字符范围示例
[cat]:匹配字符集合中的任意一个字符c、a、t
[^cat]:匹配除c、a、t以外的字符
[A-Z]:匹配字母A-Z范围内的字符
[^a-z]:匹配字母a-z范围外的字符
[a-zA-Z0-9]:匹配大小写字母和0-9范围内的字符
[\u4e00-\u9fa5]:匹配任意一个中文字符
字符组合:如果允许用户输入英文字母(不区分大小写)、数字、短横线-、下划线_的正则情况。
<style>
.success{
color: green;
}
.fail{
color: red;
}
</style>
<body>
用户名:<input type="text" id="user"><span ></span>
<br/><br/>
密码:<input type="password" id="pwd">
<script>
var reg = /^[a-zA-Z0-9_-]{6,16}$/
let user= document.getElementById('user')
let span = document.querySelector('span')
user.onblur = function () {
if (reg.test(user.value)) {
document.querySelector('span').classList.remove('fail')
document.querySelector('span').innerHTML = '用户名正确'
document.querySelector('span').classList.add('success')
}else{
document.querySelector('span').classList.remove('success')
document.querySelector('span').innerHTML = 'error'
document.querySelector('span').classList.add('fail')
}
}
</script>
</body>
(6)量词符
{m,n}:表示{}之前的数字可以出现m-n次
{n}:表示{}之前的字符可以出现n次
{n,}:匹配{}前面的字符最少n次。
?:匹配?之前的字符零次或一次。
<script>
let reg1 = /hi?t/
let str1 = 'hiit'
console.log(reg1.test(str1))
</script>
注意:exec(字符串):是正则表达式对象的方法。返回值类型是数组
<script>
let reg1 = /hi?t/
let str1 = 'hiit'
let arr = reg1.exec(str1)
console.log(arr)
</script>
+:匹配+前面的字符一次或多次
*:匹配*前面的字符零次或多次
(7)括号字符:改变限定符的范围
a.改变限定符范围之前:catch|er 匹配结果:catch、er
b.改变限定符范围之后:cat(ch|er) 匹配结果:catch、cater
c.分组:
分组前 abc{2} c出现2次
分组后 a(bc){2} bc出现2次
<script>
let reg = /catch|er/
let s1 = 'catch1'
console.log(reg.test(s1))//true
console.log(reg.exec(s1))//['catch', index: 0, input: 'catch1', groups: undefined]
s1 = 'catc'
console.log(reg.test(s1))//false
console.log(reg.exec(s1))//null
s1 = 'er'
console.log(reg.test(s1))//true
console.log(reg.exec(s1))//['er', index: 0, input: 'er', groups: undefined]
</script>
5..捕获与非捕获
(1)捕获:使用小括号可以进行分组,当小括号后面由量词符时,就表示对整个组进行操作
<script>
let reg1 = /(\d)(\d)(\d)(\d)/ //表示4位数字,每位都是0~9之间
let str1 = '1234'
console.log(reg1.test(str1))
console.log(reg1.exec(str1))//(5) ['1234', '1', '2', '3', '4', index: 0, input: '1234', groups: undefined]
</script>
(2)进行字符串的替换:replace结合正则表达式实现
<script>
let reg2 = /(\w+)\s(\w+)/
let str2 = 'Regular Capture';
// console.log(reg2.exec(str2))
let newStr = str2.replace(reg2,'$2 $1')
console.log(newStr)//Capture Regular
reg2 = /(\w+)\s(\w+)\s(\w+)/
str2 = 'Regular Capture hi'
newStr = str2.replace(reg2,'$3 $2 $1')
console.log(newStr)//hi Capture Regular
</script>
6.贪婪匹配与懒惰匹配
(1)贪婪匹配:匹配尽可能多的字符。是正则表达式的默认匹配方式
(2)懒惰匹配:匹配尽可能少的字符。通过?来实现
<script>
var str = 'wsbWEBWebwEB'
var reg1 = /w.*b/gi //贪婪匹配
console.log(reg1.exec(str))
var reg2 = /w.*?b/gi //懒惰匹配 表示只要有一次匹配成功即可,不会继续进行匹配
console.log(reg2.exec(str))
</script>
7.优先级 一级:\ 转义字符
二级:()、[]
三级:*、+、?、{n}、{n,}、{m,n}
四级:^、$、\任何元字符、任何字符
示例:验证身份证号
身份证的正则表达式为:
【过去】 /(^\d{15}$)|(^\d{17}([0-9]|X)$)/
【现在】/^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
<style>
.success{
color: greenyellow;
}
.fail{
color: red;
}
</style>
<body>
身份证<input type="text" id="id_card"><span></span>
<script>
let idCard = document.getElementById('id_card')
// 过去的身份证证号
let num = /(^[1-9]\d{14}$)|(^[1-9]\d{16}([0-9]|X)$)/
// 最新的身份证号
let num1 = /^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
idCard.onblur = function(e){
// 过去 num.test(idCard.value)
// 现在 num1.test(idCard.value)
if (num1.test(idCard.value) ) {
document.querySelector('span').classList.remove('fail')
document.querySelector('span').innerHTML = '输入正确'
document.querySelector('span').classList.add('success')
}else{
document.querySelector('span').classList.remove('success')
document.querySelector('span').innerHTML = '输入错误'
document.querySelector('span').classList.add('fail')
}
}
</script>
</body>