文章目录
事件
传统方式
<div>123</div>
var div = document.querySelector('div')
div.onclick = function (event) {
console.log(event)
}
addEventListener
div.addEventListener('click', function (event) {
console.log(event)
})
事件对象也是兼容性问题 IE678 通过winndow.event
div.onclick = function () {
console.log(window.event) //IE678只能识别这种写法
}
为了解决兼容性:
div.onclick = function (e) {
e = e || window.event
console.log(e) //这是兼容性写法
}
1.event就是一个事件对象 写到我们的侦听函数得 小括号里面 当形参来看
2.事件对象只有有了事件才存在 他是系统给我们自动创建得,不需要为我们传递参数
3.事件对象 是 我们事件得一系列相关的数据得集合 跟事件相关的 比如鼠标点击里面就包含了鼠标的相关信息,鼠标坐标等,如果是键盘事件里面就包含了键盘事件,比如判断用户按下了哪个键位都知道
4.这个事件对象我们可以自己命名 比如 even、evt、e
常见的事件对象得属性和方法
返回触发事件的对象
e.target 返回的是触发事件得对象(元素)
<div>123<div>
var div = document.querySelector('div')
div.addEventListener('click', function (e) {
console.log(e.target) //返回的<div>123</div>
})
而有一个相同的this
this 返回的是绑定事件得对象(元素)
<ul>
<li>123</li>
<li>123</li>
<li>132</li>
</ul>
var ul = document.querySelector('ul')
ul.addEventListener('click', function () {
//我们给别 绑定了事件 那么this 就指向ul
console.log(this) //返回的是<ul><li>abc</li><li>abc</li><li>abc</li></ul>
})
两者区别:
e.target 指向我们点击的对象 谁触发了这个事件 我们点击的是li e.target 指向的就是li
我们给ul 绑定了事件 那么this 就指向ul
扩展 this 有个非常相似的属性 currentTarget 在IE678兼容
和
ul.addEventListener('click', function (e) {
console.log(e.currentTarget)//返回的是<ul><li>abc</li><li>abc</li><li>abc</li></ul>
})
因为e.target IE678 不支持所以我们使用 e.srcElement 不标准IE678支持
为了使用所以我们使用兼容性写法
div.onclick = function () {
e = e || window.event
var target = e.target || e.srcElement
console.log(target)
}
返回事件类型
e.type返回事件类型
<div>123</div>
var div = document.querySelector('div')
//e.type返回事件类型 比如 click mouseover 不带on
div.addEventListener('click', fn)
div.addEventListener('mouseover', fn)
div.addEventListener('mouseout', fn)
function fn(e) {
console.log(e.type) //得到相应的事件类型
}
阻止默认行为(事件) 让链接不跳转 或者让提交按钮不提交
e.preventDefault()
<a href="http://www.baidu.com">百度</a>
var a = document.querySelector('a')
a.addEventListener('click', function (e) {
e.preventDefault() // dom 标准写法
})
在这里有一个需要注意 element.addEventListener 只支持 e.preventDefault()
传统的注册方式
<a href="http://www.baidu.com">百度</a>
- 普通浏览器 e.preventDefault(); 方法 不考虑兼容性可用
a.onclick = function (e) {
e.preventDefault()
}
- 低版本浏览器 ie678 returnValue 属性
a.onclick = function (e) {
e.returnValue
}
- 我们可以利用return false 也能阻止默认行为 没有兼容性问题
特点: return 后面的代码不执行了, 而且只限于传统的注册方式 addEventListener不支持
a.onclick = function (e) {
return false
alert(11)
}
阻止冒泡
- e.stopPropagation()
css是我们更方便辨认从上倒下的层次关系
.father {
overflow: hidden;
width: 300px;
height: 300px;
margin: 100px auto;
background-color: pink;
text-align: center;
}
.son {
width: 200px;
height: 200px;
margin: 50px;
background-color: purple;
line-height: 200px;
color: #fff;
}
上次我们提到,他的层次由 document -> html -> body -> father -> son
<div class="father">
<div class="son">son儿子</div>
</div>
在这里我们输出 document -> father -> son 作为示范
var son = document.querySelector('.son')
// e.stopPropagation()要阻止哪个冒泡就放在哪个函数里面
son.addEventListener(
'click',
function (e) {
alert('son')
},
false
)
var father = document.querySelector('.father')
father.addEventListener(
'click',
function () {
alert('father')
},
false
)
document.addEventListener('click', function () {
alert('document')
})
输出得结果为点击son块时,分别弹出son -> father -> document
当我们在son函数添加e.stopPropagation()时:
var son = document.querySelector('.son')
son.addEventListener(
'click',
function (e) {
alert('son')
e.stopPropagation() // stop 停止 Propagation 传播
},
false
)
var father = document.querySelector('.father')
father.addEventListener(
'click',
function () {
alert('father')
},
false
)
document.addEventListener('click', function () {
alert('document')
})
注意:e.stopPropagation()要阻止哪个冒泡就放在哪个函数里面
写在son函数里面,点击father时不能阻止冒泡
注意:e.stopPropagation()虽然很方便,但是IE6、7、8并不支持,我们在IE低版本只有通过window.event.cancelBubble = true来实现阻止冒泡
var son = document.querySelector('.son')
son.addEventListener(
'click',
function (e) {
alert('son')
e.cancelBubble = true // 非标准 cancel 取消 bubble 泡泡
},
false
)
var father = document.querySelector('.father')
father.addEventListener(
'click',
function () {
alert('father')
},
false
)
document.addEventListener('click', function () {
alert('document')
})
为了解决兼容性问题,所以我们用兼容性的写法
if (e && e.stopPropagation) {
e.stopPropagation()
} else {
window.event.cancelBubble = true
}
事件委托
事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点
<ul>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
</ul>
var ul = document.querySelector('ul')
var flag = 0
ul.addEventListener('click', function (e) {
// alert('知否知否,点我应有弹框在手!')
// e.target //这个可以得到我们点击的对象
e.target.style.backgroundColor = 'pink'
})
鼠标事件
禁用右键
选中文字无法右击出菜单
//1.contextmenu禁用右击菜单
document.addEventListener('contextmenu', function (e) {
e.preventDefault()
})
禁止鼠标选中
document.addEventListener('selectstart', function (e) {
e.preventDefault()
})
扩展 禁用F12键
document.onkeydown = document.onkeyup = document.onkeypress = function (
event
) {
var e = event || window.event || arguments.callee.caller.arguments[0]
if (e && e.keyCode == 123) {
mAlert()
e.returnValue = false
return false
}
}
function mAlert() {
alert('禁止操作控制台')
}
document.onmousedown = function mdClick(event) {
var e = event || window.event || arguments.callee.caller.arguments[0]
if (e.button == 2 || e.button == 3) {
mAlert()
}
}
鼠标事件对象
e.clientX 和 e.clientY 只获取可视区 就算文章很长有滚动条得到的也只是可视区的坐标
document.addEventListener('click', function (e) {
console.log(e.clientX) //距离左边距距离坐标
console.log(e.clientY) //距离上边距距离坐标
})
e.pageX 和 e.pageY 获取整个文档 e.pageY随着文档长度而变化 此方法有兼容性问题 ie9以上才支持
body {
height: 3000px;
}
document.addEventListener('click', function (e) {
console.log(e.pageX) //距离整个页面大的左边距距离坐标
console.log(e.pageY) //距离整个页面大的上边距距离坐标
})
e.screenX 和 e.screenY是得到整个屏幕坐标
body {
height: 3000px;
}
document.addEventListener('click', function (e) {
console.log(e.screenX) //距离电脑屏幕的左边距距离坐标
console.log(e.screenY) //距离电脑屏幕的上边距距离坐标
})
下为图解
鼠标事件案例
mousemove只要我们鼠标移动1px 就会触发这个事件
- 因为我们是在页面移动,所以我们给document注册事件
- 图片·移动距离不占用位置,使用绝对定位
- 核心原理: 每次鼠标移动,我们都会获得最新的鼠标坐标, 把这个x和y坐标做为图片的top和left 值就可以移动图片
<style>
img {
position: absolute;
top: 2px;
}
</style>
<img src="images/angel.gif" alt="" />
<script>
var pic = document.querySelector('img')
document.addEventListener('mousemove', function (e) {
// 1. mousemove只要我们鼠标移动1px 就会触发这个事件
// console.log(1);
// 2.核心原理: 每次鼠标移动,我们都会获得最新的鼠标坐标, 把这个x和y坐标做为图片的top和left 值就可以移动图片
var x = e.pageX
var y = e.pageY
console.log('x坐标是' + x, 'y坐标是' + y)
//3 . 千万不要忘记给left 和top 添加px 单位
pic.style.left = x - 50 + 'px'
pic.style.top = y - 40 + 'px'
})
</script>
常见的键盘事件
onkeyup 按键弹起的时候 触发
onkeydown 按键按下的时候 触发
keypress 按键按下的时候 触发 注意 他不识别功能键 比如 ctrl shift 左右键等
//常见的键盘事件
// document.onkeyup = function () {
// console.log('我弹起了')
// }
document.addEventListener('keyup', function () {
console.log('我弹起了')
})
document.addEventListener('keydown', function () {
console.log('我按下了')
})
document.addEventListener('keypress', function () {
console.log('我按下了press')
})
注意 : 优先级 keydown > keypress 左后执行keyup
键盘对象
键盘事件对象keyCode属性可以i得到相应的ASCII码值
我们的 keyup 和 keydown 事件不区分字母大小写 a 和 A 得到的都是65
我们的 keypress 虽然不知别功能键 但是区分字母大小写 返回不同的
<script>
ASCII码
document.addEventListener('keyup', function (e) {
console.log('keyup:' + e.keyCode)
if (e.keyCode === 65) {
alert('您按下了a键')
} else {
alert('您没有按下了a键')
}
})
// 我们可以利用keyCode返回的ASCII值确定我们按的哪个值
document.addEventListener('keypress', function (e) {
console.log('keypress:' + e.keyCode)
})
</script>
ASCII表
键盘对象案例
模拟京东按键快速定位搜索框
<input type="text" />
<script>
// 核心思路: 检测用户是否按下了s 键,如果按下s 键,就把光标定位到搜索框里面
// 使用键盘事件对象里面的keyCode 判断用户按下的是否是s键
// 搜索框获得焦点: 使用 js 里面的 focus() 方法
var search = document.querySelector('input')
// document.addEventListener('keydown', function (e) {
// // console.log(e.keyCode);
// if (e.keyCode === 83) {
// search.focus()
// }
// })
//使用keydown时会在按下同时执行所以会输出s
document.addEventListener('keyup', function (e) {
// console.log(e.keyCode);
if (e.keyCode === 83) {
search.focus()
}
})
</script>
键盘事件-模拟京东快递单号查询案例
<body>
<div class="search">
<div class="con">123</div>
<input type="text" placeholder="请输入您的快递单号" class="jd" />
</div>
</body>
```html
```css
<style>
* {
margin: 0;
padding: 0;
}
.search {
position: relative;
width: 178px;
margin: 100px;
}
.con {
display: none;
position: absolute;
top: -40px;
width: 171px;
border: 1px solid rgba(0, 0, 0, 0.2);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
padding: 5px 0;
font-size: 18px;
line-height: 20px;
color: #333;
}
.con::before {
content: '';
width: 0;
height: 0;
position: absolute;
top: 28px;
left: 18px;
border: 8px solid #000;
border-style: solid dashed dashed;
border-color: #fff transparent transparent;
}
</style>
<script>
var con = document.querySelector('.con')
var jd_input = document.querySelector('.jd')
jd_input.addEventListener('keyup', function () {
// console.log('123456')
if (this.value == '') {
con.style.display = 'none'
} else {
con.style.display = 'block'
con.innerText = this.value
}
})
//当我们失去焦点就影藏这个从盒子
jd_input.addEventListener('blur', function () {
con.style.display = 'none'
})
// 当我们获取焦点就影藏这个从盒子
jd_input.addEventListener('focus', function () {
if (this.value == '') {
con.style.display = 'none'
} else {
con.style.display = 'block'
}
})
</script>