第十二天笔记
事件流的传播流程
事件流的传播有三个阶段
-
捕获阶段
从最外层找到对应的事件执行的元素
-
目标阶段
找到这个元素 执行对应的事件
-
冒泡阶段
逐层向上冒泡执行对应的事件
<div onclick="alert(2)">
<button onclick="alert(1)"></button>
</div>
<script>
document.body.onclick=function(){
console.log(3);
}
</script>
以上的这个示例 会从button 开始不断向上执行 直到window停止 所以对应的执行结果为1,2,3
如果我们不想触发对应的外层的事件 只是想触发本身的事件 那么我们就需要禁止事件冒泡了
禁止事件冒泡的处理
stopPropagation
document.body.onclick=function(){
console.log(3);
e.stopPropagation()
}
cancelBubble(event对象的属性)
console.log(e.cancelBubble);// 阻止冒泡 默认值为false
console.log(e.returnValue);// 返回的value值 返回的是true 可以走 false不可以走 默认为true
兼容写法
e.stopPropagation()?e.stopPropagation():e.cancelBubble=true
事件流的两种模式
-
冒泡模式(从里到外 逐层执行对应的事件)
冒泡模式是常用的模式,他现在默认设计的就是冒泡模式
-
捕获模式(从外到里 逐层执行对应的事件)
捕获模式是火狐提出来的模式,ie对应的6,7,8 不支持。 现在的模式一般很少使用捕获模式
默认行为
元素标签尤其默认行为( a标签会跳转页面),对应的事件也有其默认行为(contextmeun 会出现对应的菜单栏)
禁止默认行为
-
preventDefault
-
returnValue event的属性
-
return false 一般不用一定要放在最后
document.querySelector('a').onclick = function (e) {
e = e || window.event
console.log('点击');
// a标签会默认刷新页面 为了禁止这个操作 那么我们可以禁止他的默认行为
e.defaultPrevented // 是否阻止了默认行为 只读
// e.preventDefault()// preventDefault 阻止默认行为
e.returnValue=false// 兼容ie的
// 兼容写法
e.preventDefault()? e.preventDefault():e.returnValue=false
}
// 对应的右键点击
document.oncontextmenu=function(e){
console.log('右键点击');
// e.preventDefault()? e.preventDefault():e.returnValue=false
return false // 一定要在最后
}
示例
右键点击出现对应的菜单栏 这个菜单栏自定义(前进功能 后退功能 刷新功能 换肤 打印·)
// 右键点击出现对应的菜单栏 这个菜单栏自定义(前进功能 后退功能 刷新功能 换肤 打印·)
document.oncontextmenu = function (e) {
// 渲染ul
document.body.innerHTML = `
<ul class="box">
<li>前进</li>
<li>后退</li>
<li>刷新</li>
<li>换肤</li>
<li>打印</li>
</ul>
`
// 获取元素
var box = document.querySelector('.box')
var li = document.querySelectorAll('li')
// 调整box的位置
box.style.top = e.pageY + 'px'
box.style.left = e.pageX + 'px'
// 取消默认事件
e.preventDefault()
// li委托事件 鼠标移入变色
box.onmouseover=function(e){
// console.log(111);// 测试
if(e.target.nodeName=='LI'){
for(var l of box.children){
l.style.backgroundColor='#fff'
}
// console.log(e.target);// 测试
e.target.style.backgroundColor='#ccc'
}
}
// 给li标签添加事件
li[0].onclick = function (e) {
// console.log(111);// 测试
history.forward()
}
li[1].onclick = function () {
history.back()
}
li[2].onclick = function () {
location.reload()
}
li[3].onclick = function () {
changeSkin(document.body)
}
li[4].onclick = function () {
window.print()
}
// 点击取消右键框
box.onclick= function(e){
if(e.target.nodeName=='LI'){
this.innerHTML=''
}
}
}
// 换色代码
function changeSkin(element) {
var r = Math.random() * 255
var g = Math.random() * 255
var b = Math.random() * 255
element.style.background = `rgba(${r},${g},${b})`
}
事件监听器
eventListener 他是一个标准的观察者模式,它是通过对应的监听器来监听事件的触发和执行
主要有两个方法
-
addEventListener 添加事件监听器
传入对应的事件名及处理函数 以及对应的是否冒泡
注意事项
addEventListener 可以在一个事件中传入多个处理函数
EventListenter 支持自定义事件名
onclick 赋值不支持多个处理函数
-
removeEventListener 移除事件监听器
移除对应添加的事件监听器,传入事件名、处理函数、是否冒泡 每个都必须和添加的事件监听器一致 不然不能被移除
注意事项
如果添加事件监听器的时候传入处理函数为匿名函数 那么不能被移除
拖拽
原理
-
给对应需要拖拽的元素添加按下事件
-
再按下事件内添加对应的移动事件
-
再按下事件内添加对应的弹起事件 在弹起事件中释放移动事件 释放弹起事件
基础拖拽
思路
-
获取拖拽元素
-
给拖拽元素添加按下事件 并记录按下的坐标
-
给区间元素添加移动事件 并记录移动的坐标
-
在区间元素的鼠标移动事件中设置对应的拖拽元素的坐标
-
在document中添加鼠标弹起事件 并释放之前的移动事件及自身的弹起事件
区间拖拽
offset家族 (属于元素对象 element对象)
// offset家族
// offsetParent 偏移的父元素
// 获取inner
var inner=document.querySelector('.inner')
console.log(inner.offsetParent);// 找有定位的上层元素
console.log(inner.offsetLeft);// 左偏移 不会计入父元素本身的margin值 但会计入padding值
console.log(inner.offsetTop);// 右偏移
console.log(inner.offsetWidth);// 偏移元素的宽度
console.log(inner.offsetHight);
思路
-
获取拖拽的元素
-
给拖拽元素添加鼠标按下事件 并记录按下的坐标(在对应的盒子里的坐标)
-
在按下事件内给区间元素添加鼠标移动事件 并记录每次移动的坐标
-
在区间元素的鼠标移动事件中 获取对应的区间元素的位置 及 能够移动的距离 (区间元素的宽/高度 - 自身的宽/高度)
-
设置移动元素处在区间元素的位置 移动位置在父元素的坐标 = 页面的位置 - 父元素离页面的位置 - 鼠标点击的位置
-
对应坐标位置进行区间判断 小于0的时候值应该设置为0 大于能够移动的距离设为最大的距离
-
在按下事件内在document中添加鼠标弹起事件 并释放之前的移动事件及自身的弹起事件
<div>
<button>
移动的按钮
</button>
</div>
<script>
var box = document.querySelector('div')
var button = document.querySelector('button')
button.onmousedown = function(e){
e = e || window.event
//记录在而盒子上的坐标
var x = e.offsetX
var y = e.offsetY
//在box中移动
box.onmousemove = function(e){
e = e || window.event
//获取区间元素的位置
var bx = this.offsetLeft
var by = this.offsetTop
//获取能够移动的最大距离
var maxX = this.offsetWidth - button.offsetWidth
var maxY = this.offsetHeight - button.offsetHeight
//移动位置在父元素的坐标 = 页面的位置 - 父元素离页面的位置 - 鼠标点击的位置
var targetX = e.pageX - bx - x
var targetY = e.pageY - by - y
//进行区间判断
if(targetX < 0){
targetX = 0
}
if(targetY < 0){
targetY = 0
}
if(targetX > maxX){
targetX = maxX
}
if(targetY > maxY){
targetY = maxY
}
button.style.left = targetX + 'px'
button.style.top = targetY + 'px'
}
document.onmouseup = function(){
box.onmousemove = document.onmouseup = null
}
}
</script>
封装一个方法找盒子到页面的距离
function getBoxToPageDistance(element){标签:function,第十二天,元素,笔记,事件,var,console,document From: https://www.cnblogs.com/balloontrue/p/17142143.html
var distance = {
x:0,
y:0
} //距离对象
while(element.offsetParent){ //找到body就停止
distance.x += element.offsetLeft
distance.y += element.offsetTop
element = element.offsetParent
}
return distance
}