Day10.事件下(学习日记10)

事件的传播流程

事件流的传播有三个流程

  • 捕获阶段
  • 目标阶段
  • 冒泡阶段

事件流的两种模式

冒泡模式(从里到外 逐层执行对应的事件)

冒泡模式是常用的模式,他现在默认设计模式就是冒泡模式.

```html

<div οnclick="alert(1)">

    <button οnclick="alert(2)"></button>

</div>

<script>

    document.body.onclick = function () {

        alert(3)

    }

    document.onclick = function () {

        alert(4)

    }

    window.onclick = function () {

        alert(5)

    }

</script>

以上这个示例 会从button开始不断向上执行 直到window停止 所以对应的执行结果为2 1 3 4 5

如果我们不想触发对应的外层事件 只是想触发本身的事件 那我们就需要禁止冒泡事件了

禁止事件冒泡的处理

stopPropagation(event对象的方法 对于低版本的IE浏览器不支持)

document.querySelector('button').onclick = function(e){

    //事件源对象

    e = e || window.event

    //禁止事件冒泡的方法

    e.stopPropagation()

    alert(2)

}

cancelBubble(event对象的属性)

//cancelBubble 取消冒泡 默认为false

e.cancelBubble = true

兼容写法

e.stopPropagation?e.stopPropagation():e.cancelBubble = true

捕获模式(从外到里 逐层执行对应的事件)

捕获模式是火狐浏览器提出来的模式,IE对应的6,7,8版本不支持.现在的模式一般很少用到捕获模式.

默认行为

元素标签有其默认行为(a标签会默认跳转页面 form标签里面的submit默认提交(刷新),对应的事件也有其默认行为(contextmenu会出现对应的菜单栏等))

e.defaultPrevented 检查当前是否禁止默认行为

console.log(e.defaultPrevented) //是否阻止默认行为 只读 默认为false

禁止默认行为

preventDefault(event对象的方法)

e.preventDefault() //preventDefault阻止默认行为

returnValue(event对象的属性)

e.returnValue = false //兼容ie的

兼容写法

e.preventDefault?e.preventDefault():e.returnValue = false

return false

//对应的右键点击

window.oncontextmenu = function(e){

    console.log('右键点击了')

    // e.preventDefault?e.preventDefault():e.returnValue=false

    return false //一定要放在最后

}

示例

右键点击出现对应的菜单栏 这个菜单栏自定义(前进功能 后退功能 刷新功能 换肤 打印)

<style>

        * {

            margin: 0;

            padding: 0;

        }

        ul {

            list-style: none;

            width: 80px;

            border: 2px solid black;

            display: none;

            position: absolute;

            border-radius: 5px;

        }

        li {

            border-bottom: 1px solid #000;

            width: 80px;

            box-sizing: border-box;

            line-height: 30px;

            text-align: center;

        }

    </style>

</head>

<body>

    <a href="https://www.4399.com/">4399</a>

    <ul>

        <li οnclick="history.forward()">前进</li>

        <li οnclick="history.back()">后退</li>

        <li οnclick="location.reload()">刷新</li>

        <li οnclick="document.body.style.backgroundColor=randomColor()">换肤</li>

        <li οnclick="print">打印</li>

    </ul>

</body>

</html>

<script>

    //事件委托

    //获取父元素

    var ul = document.querySelector('ul')

    //移入对应的ul内

    ul.onmouseover = function (e) {

        e = e || window.event

        if (e.target.nodeName == 'LI') {

            //排他

            for (var li of ul.children) {

                li.style.backgroundColor = '#fff'

            }

            e.target.style.backgroundColor = '#ccc'

        }

    }

    //右键点击

    window.oncontextmenu = function (e) {

        e = e || window.event

        e.parventDefault ? e.parventDefault() : e.returnValue = false

        //显示ul

        ul.style.display = 'block'

        //改变ul的定位

        ul.style.left = e.pageX + 'px'

        ul.style.top = e.pageY + 'px'

    }

    //点击对应的li 使用事件委托隐藏对应的ul

    ul.onclick = function (e) {

        e = e || window.event

        if (e.target.nodeName == 'LI') {

            this.style.display = 'none'

        }

    }

    function randomColor() {

        var r = Math.random() * 256

        var g = Math.random() * 256

        var b = Math.random() * 256

        return `rgb(${r},${g},${b})`

    }

</script>

事件监听器

eventListener他是一个标准的观察者模式,他是通过对应的监听器来监听事件的触发和执行.

主要有两个方法

  • addEventListener 添加事件监听器
  • removeEventListener 移除事件监听器

addEventListener

传入对应的事件名及处理函数以及对应的是否冒泡

//获取按钮

var btn  = document.querySelector('button')

//添加事件监听器 传入 事件名 处理函数  是否捕获(默认的事件模式 冒泡 false 捕获 true)

// btn.addEventListener('click',function(){

//   console.log('按钮点击了')

// })//指定为冒泡模式

// btn.addEventListener('click',function(){

//   console.log('按钮点击了1')

// },true)//指定为捕获模式 先执行

// btn.addEventListener('click',function(){

//   console.log('按钮点击了2')

// })

//addEventListener 他可以给一个事件添加多个处理函数

//一个事件 有一个处理函数的数组

//事件监听器中的事件名 支持自定义

// btn.addEventListener('dblclick',function(){

//   console.log('双击')

// })

//直接使用onclick 进行赋值的操作他会被覆盖也就是说他只有一个处理函数 后写会覆盖先写的 (属性赋值操作)

// document.querySelector('div').onclick = function(){

//   console.log('div被点击了')

// }

btn.addEventListener('click',handler,false)//指定为冒泡模式

注意事项

  • addEventListener可以在一个事件中传入多个处理函数(一个事件对应一个处理函数组)
  • EventListener支持自定义事件名
  • 属性事件赋值不支持多个处理函数(因为会被覆盖)

removeEventListener

移除对应的添加事件的监听器,传入事件名,处理函数,是否冒泡 每个都必须和添加的事件监听器一致不能不能被移除

btn.addEventListener('click',handler,false)//指定为冒泡模式

// 要移除的事件名 要移除的处理函数(也要一致 如果是匿名函数那么就不能被移除 对象比对的是地址) 模式也要一致

btn.removeEventListener('click',handler,false)  

function handler(){

    console.log('按钮点击了')

}

注意事项

如果添加事件监听器的时候传入处理函数为匿名处理函数 那么不能被移除(对象比对的是地址)

拖拽

拖拽原理

  • 给对应的需要拖拽的元素添加鼠标按下事件
  • 再按下事件内添加给区间的元素对应的鼠标移动事件
  • 在按下事件内给document添加对应的鼠标弹起事件  在弹起事件中释放移动事件及释放弹起事件

基础拖拽

  • 获取拖拽的元素
  • 给拖拽元素添加鼠标按下事件 并记录按下的坐标(在对应的盒子里的坐标)
  • 在按下事件内给区间元素添加鼠标移动事件 并记录每次移动的坐标
  • 在区间元素的鼠标移动事件中 设置对应的拖拽元素的坐标(移动的坐标=当前的坐标-鼠标点击位置的坐标+'px')
  • 在按下事件内在document中添加鼠标弹起事件 并释放之前的移动事件及自身的弹起事件

<div></div>

<script>

var box = document.querySelector('div')

box.onmousedown = function(e){

    e = e || window.event

    //记录在而盒子上的坐标

    var x = e.offsetX

    var y = e.offsetY

    //在document中移动

    document.onmousemove = function(e){

        e = e || window.event

        //获取页面上的坐标

        var currentX = e.pageX

        var currentY = e.pageY

        //移动的坐标 = 当前的坐标 - 鼠标点击位置的坐标 + 'px'

        box.style.left = currentX - x + 'px'

        box.style.top = currentY - y + 'px'

    }

    document.onmouseup = function(){

        document.onmousemove = null

        document.onmouseup = null

    }

}

</script>

区间拖拽

  • 获取拖拽的元素
  • 给拖拽元素添加鼠标按下事件 并记录按下的坐标(在对应的盒子里的坐标)
  • 在按下事件内给区间元素添加鼠标移动事件 并记录每次移动的坐标
  • 在区间元素的鼠标移动事件中 获取对应的区间元素的位置 及 能够移动的距离 (区间元素的宽/高度 - 自身的宽/高度)
  • 设置移动元素处在区间元素的位置  移动位置在父元素的坐标 =  页面的位置 - 父元素离页面的位置 鼠标点击的位置
  • 对应坐标位置进行区间判断 小于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){

    var distance = {

        x:0,

        y:0

    } //距离对象

    while(element.offsetParent){ //找到body就停止

        distance.x += element.offsetLeft

        distance.y += element.offsetTop

        element = element.offsetParent

    }

    return distance

}

谢谢观看!

不知名选手铉

2023/2/21 20:02

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值