事件(下)

1、事件流

事件流是描述的从页面接受事件的顺序,当几个都具有事件的元素层叠在一起的时候, 那么你点击其中一个元素,并不是只有当前被点击的元素会触发事件,而层叠在你点击范围的所有元素都会触发事件。事件流包括两种模式:冒泡和捕获。

(1)事件冒泡

事件冒泡是从里往外逐个触发。但是一般我们只在指定的节点上添加事件, 而不想让其传递到下层节点触发事件, 这样我们就需要阻止事件冒泡。

阻止事件冒泡

1, 取消冒泡, IE
e.cancelBubble = true;
2, 停止传播, 非IE
e.stopPropagation();

e.stopPropagation?e.stopPropagation():e.cancelBubble = true  //事件冒泡的兼容写法
       //从里到外执行的
       bigbox.onclick = function(e){
         console.log('大盒子的点击事件触发了');
         this.style.backgroundColor = 'red'
       }
       innerBox.onclick = function(e){
         console.log('里面的盒子的点击事件触发了');
         this.style.backgroundColor = 'blue'
       }
       content.onclick = function(e){
         e = e || event //兼容ie
         console.log('主体内容的点击事件触发了');
         this.style.backgroundColor = 'yellow'
        //  e.stopPropagation(); //阻止事件冒泡 stopPropagation 函数
         e.cancelBubble = true //ie的兼容 取消事件冒泡 未来可能会废弃
        //  e.stopPropagation?e.stopPropagation():e.cancelBubble = true 兼容写法
       }

(2)事件捕获

事件捕获, 是从外往里逐个触发。现代的浏览器默认情况下都是事件冒泡的模式。

2、默认行为

默认行为指的是一个元素会自带的行为称为默认行为 a标签的默认行为会跳转 form标签里面submit按钮默认会提交(刷新页面)鼠标右键会出现一个菜单栏 等等一系列的问题。有些时候我们不需要这些行为的产生 那么我们就需要阻止默认行为。

阻止默认行为

  • e.preventDefault() 函数 (prevent)
  • e.returnValue = false ie的兼容
  • return false 直接结束对应的操作
e.preventDefault?e.preventDefault():e.returnValue = false   //阻止默认行为的兼容写法
        document.querySelector('a').onclick = function(e){
            e = e || event
            // e.preventDefault() //阻止默认行为
            // e.returnValue = false //ie的兼容
            console.log('hello');
            //一定是放在最后面
            return false //函数的结束 gc垃圾回收机制会准备回收
        }
        //阻止表单的默认提交行为
        document.querySelector('form').onsubmit= function(e){
            e = e || event
            // e.preventDefault() //阻止默认行为
            e.preventDefault?e.preventDefault():e.returnValue = false //兼容
            console.log('表单提交');
        }

3、拖拽

所谓拖拽: 就是按住元素后移动位置, 最后松开的过程

拖拽的思路:

  • 给拖拽的元素添加mousedown的事件 记录当前点击的位置
  • 给对应的容器添加mousemove事件 记录每次移动的位置
  • 给对应的容器添加mouseup 事件 清除上述mousemove事件
        //获取div
        var box = document.getElementById('box')
        //给div添加mousedown事件
        box.onmousedown = function(e){
            e = e || event
            //记录的是鼠标在div里面的位置
            //在mousedown里面记录按下的位置
            var x = e.offsetX
            var y = e.offsetY
            // var x = e.pageX-box.offsetLeft
            // var y = e.pageY-box.offsetTop
            //给document添加mousemove事件
            document.onmousemove = function(e){
                e = e || event
                //记录每次的位置  在document里面的位置
                var currentX = e.pageX
                var currentY = e.pageY
                //并且设置div的位置
                box.style.left = currentX - x + "px"
                box.style.top = currentY - y + "px"
            }
            //给document添加mouseup事件
            document.onmouseup = function(){
                //清除对应的mousemove事件
                document.onmousemove = null
            }
        }

4、获取style样式

style属性 只能获取标签内容style属性里面存在的一些样式
如果你需要获取对应的全局所有地方设置样式 我们就需要采用一些方法

getComputedStyle 方法属于window的方法

window.getComputedStyle(元素对象,null) //返回给你的是一个样式对象

ie兼容

element.currentStyle //返回给你一个样式对象
        var box =  document.querySelector('div')
        //通过style来获取样式 返回CSSStyleDeclaration对象 这个对象里面只存在对应style里面设置的样式
        console.log(box.style.width); //100px
        console.log(box.style.height); //空文本
        //明显可以看出对应的style直接获取是不足 他获取不到内联样式以及外联的样式
        //所以我们对应的window有对应的方法来获取所有地方的样式
        var styleObj = window.getComputedStyle(box) //这个方法是属于window 传入元素
        console.log(styleObj.width);
        console.log(styleObj.height);
        console.log(styleObj.backgroundColor);
        console.log(styleObj.color); //返回默认值
        //IE的兼容
        console.log(box.currentStyle);//返回样式对象
        //兼容写法
       var style =  window.getComputedStyle?window.getComputedStyle(box):box.currentStyle
        //方法的封装
        function getStyle(element,attr){
            var style =  window.getComputedStyle?window.getComputedStyle(element):element.currentStyle
            return style[attr]
        }
        console.log(getStyle(box,'height'));

5、事件委托

指的是将对应的子元素的事件添加给父元素,用e.target来获取真实操作的元素 从而完成相关的操作(不能用到事件委托的 mouseenter 和 mouseleave 以及 mousemove..)

          //事件委托  利用父元素添加事件 通过e.target获取真实的操作元素来进行相关的操作
          //当你有许多需要同时添加一个事件行为的同级元素 这个时候我们不给这些元素加事件
          // 而是给他的父元素添加事件 称为事件委托
          gameList.onmouseover = function(e){
            e = e || event
            //控制对应的li标签的背景颜色变化 得到实际的触发对象 target
            if(e.target.nodeName == 'LI'){
                 //先排他
                for(var i=0;i<games.length;i++){
                    this.children[i].style.backgroundColor = 'black'
                }
                e.target.style.backgroundColor = 'red'
            }
          }
    //    5, 选择某一项, 将顶部的名称改成你选择的游戏名称
          gameList.onclick = function(e){
            e = e || event
            if(e.target.nodeName == 'LI'){ //如果当前的e.target是li的话 才执行对应的操作
                title.innerText =  e.target.innerText
            }
          }

6、offset家族

  • offsetParent 偏移的父元素(一层一层的向上找 找到定位的元素就是对应的父元素 有定位的上层元素就他的父元素 找不到的就是body)
  • offsetLeft 基于偏移的父元素的左偏移量
  • offsetTop 基于偏移的父元素的上偏移量
  • offsetHeight 获取偏移元素的高度(包含border以及padding)
  • offsetWidth 获取偏移元素的宽度(包含border以及padding)

7、区间拖拽

指的是在一个区间内进行拖拽

       //拖拽的方法实现 第一个是移动的盒子 第二个在哪移动
       function tuoch(moveBox,box){
         //给moveBox添加按下事件 记录一下当前鼠标在moveBox里面点击的位置
         moveBox.onmousedown = function(e){
            e = e || window.event
            //获取对应的第一次按下的位置
            var firstX = e.offsetX
            var firstY = e.offsetY
            // console.log(document.body.offsetParent); //偏移的父元素
            //给box添加move事件 记录每次的位置 在box的位置 设置moveBox在box的定位
            box.onmousemove = function(e){
                e = e || event
                //这个108是对应的box离body的距离 这个距离就是box偏移的距离
                //offsetLeft 得到基于父元素左偏移量 offsetTop 得到基于父元素的上偏移量
                //offsetParent 基于的父元素 基于定位的 他会一层层往上找 找到定位的父元素就基于他 如果没有找到就基于body
                //有奶便是娘 谁有定位他就基于谁
                var currentX = e.pageX - getOffset(this).left
                var currentY = e.pageY - getOffset(this).top
                var targetX = currentX - firstX
                var targetY = currentY - firstY
                //判断边界 offsetWidth 得到盒子的宽度 offsetHeight得到盒子的高度
                if(targetX<0){
                    targetX = 0
                }
                if(targetY<0){
                    targetY = 0
                }
                if(targetX>this.offsetWidth-moveBox.offsetWidth){
                    targetX = this.offsetWidth-moveBox.offsetWidth
                }
                if(targetY>this.offsetHeight-moveBox.offsetHeight){
                    targetY = this.offsetHeight-moveBox.offsetHeight
                }
                // 设置moveBox在box的定位
                moveBox.style.left = targetX + 'px'
                moveBox.style.top = targetY + 'px'
            }
            //给box添加弹起事件 清除box的move事件
            document.onmouseup = function(){
                box.onmousemove = null
            }
        }
       }

获取对应的盒子离最外层body的left值及top值

        //获取对应的元素离body的距离 传入一个元素
        function getOffset(element) {
            var left = 0
            var top = 0
            while (element) {
                left += element.offsetLeft
                top += element.offsetTop
                element = element.offsetParent
            }
            return {
                left,
                top
            }
        }

8、事件监听器

事件监听器, 是JS事件中的一种事件触发机制, 我们可以通过添加事件监听器的方式给元素添加事件及执行函数。

1、添加事件监听器

box.addEventListener(“click”, func, false) : 给box元素添加点击事件(click), 以及事件执行函数func. 针对该函数的三个参数作说明:

  • 第一个参数(“click”) : 事件名称(前面没有on)
  • 第二个参数(func): 事件执行函数名称(没有双引号, 也没有())
  • 第三个参数(false/true) : 是否使用捕捉(反向冒泡),默认false,为冒泡

2、移除事件监听器

box.removeEventListener(“click”, func) : 将box元素的点击事件(click), 以及对应的事件执行函数func移除
注: 这里只会删除使用box.addEventListener()方法添加的事件监听器

        //是否捕获 默认为不捕获(冒泡)
        // 同时给一个事件加多个处理函数 (事件只会调用一次)
        btn.addEventListener('click',function(){
            console.log('点击了');
        },true)
        btn.addEventListener('click',function(){
            console.log('点击了1');
        },true)
        btn.addEventListener('click',function(){
            console.log('点击了2');
        },true)
        btn.addEventListener('click',function hello(){
            console.log('点击了3');
        })
        btn.removeEventListener('click',function hello(){
            console.log('点击了3');
        })//不能被移除
        //移除事件监听器 移除事件监听器根据对应的处理函数来的
        //这个俩个函数对象不是一个对象 比对出不来 所以就删不掉
        //所以我们如果需要删除对应的处理函数的话 那么必须在监听的时候 就要保证这个处理函数和对应的删除的时候的处理函数是一个
        //正确示例
        function sayHello(){
            console.log('hello');
        }
        div.addEventListener('click',sayHello)
        div.removeEventListener('click',sayHello)

兼容写法

        //移除函数
        function removeEvent(obj, type, fn, useCapture){
              if (obj.removeEventListener) {
        	obj.removeEventListener(type, fn, useCapture);
              }
              else {
        	obj.detachEvent("on"+type, fn);
              }
            //三元的写法  obj.removeEventListener?obj.removeEventListener(type,fn,useCapture):obj.detachEvent("on"+type, fn);
        }
        //添加函数
        function addEvent(obj, type, fn, useCapture){
              if (obj.addEventListener) {  
        	obj.addEventListener(type, fn, useCapture);
              }
              else {
        	obj.attachEvent("on"+type, fn);
              }
                //三元的写法  obj.addEventListener?obj.addEventListener(type,fn,useCapture):obj.attachEvent("on"+type, fn);
        }
posted @ 2022-08-09 19:01  ^-^!  阅读(45)  评论(0编辑  收藏  举报