事件(下)

75 阅读4分钟

事件(下)

事件的传播行为

  • 捕获阶段(从最外层的元素(body)找到目标元素)
  • 目标阶段(执行对应的对应的目标元素的事件)
  • 冒泡阶段 (逐层向上冒泡 直到找到body为止)

事件的触发模式

冒泡模式 (默认)
<!--打印流程  button -> div -> body -->
<body onclick="console.log('body的事件')">
  <div onclick="console.log('div的事件')">
    <button onclick="console.log('button的事件')">点击</button>
  </div>
</body>
禁止事件冒泡(event对象的方法)
  • stopPropagation 方法

    e.stopPropagation()
    
  • cancelBubble 属性

    //cancelBubble属性 取消冒泡 默认为false
    e.cancelBubble = true
    
  • 兼容写法

    e.stopPropagation? e.stopPropagation() : e.cancelBubble = true
    
捕获模式

默认行为

在某些内容中自带一些行为,这些被称为默认行为(a 标签跳转行为 form表单中的submit按钮提交行为 图片的拖动行为...)

默认行为默认是拥有的,也就是没有被禁止。

禁止默认行为的方法
  • preventDefault 方法

    //禁止默认行为
    e.preventDefault() //禁止默认行为 存储兼容问题
    
  • returnValue 属性

    //兼容ie的写法
    e.returnValue = false
    
  • return false

    //放到最后 解决禁止默认行为
    return false
    
  • 兼容写法

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

事件监听器(有兼容问题)

eventlistener (对象的俩个方法)

  • 添加事件监听器 addEventListener

    //添加事件监听器 给它进行一个监听 
    //第一个传入的是对应的事件名(任意事件名) 第二个传入是对应的处理函数 第三个参数为是否为捕获模式
    //一个事件可以有多个处理函数 (发布者订阅者  观察者(observer))
    btn.addEventListener('click',handler)
    btn.addEventListener('dblclick',handler,true)
    btn.addEventListener('click',function(){
        console.log('你好事件')
    },true)
    btn.addEventListener('click',function(){
        console.log('世界那么大')
    },true)
    function handler(){
        console.log('你好')
    }
    
  • 移除事件监听器 removeEventListener

    //removeEventListener 移除监听器 通过对应的处理函数和事件名 优先比对事件名 比对对应的处理函数及是否捕获
    //只能移除对应的addEventListenter添加的
    btn.removeEventListener('click',handler)
    //不能被移除 处理函数不是同一个
    btn.removeEventListener('click',function(){
        console.log('你好事件')
    },true)
    
注意事项
  • 添加事件监听器必须传入俩个参数 一个为事件名一个为对应的处理函数 还可以传入第三个参数为是否捕获
  • 移除事件监听器 必须保证传入的事件名一致 及对应的传入的处理函数为一个对象 以及第三个参数一致 才能移除
  • removeEventListener只能移除addEventListener添加的事件监听

拖拽

全局拖拽

实现步骤
  • 给需要拖拽的元素添加鼠标按下事件 (mousedown)
  • 记录按下的位置 (记录当前元素内按下的坐标 e.offsetX, e.offsetY)
  • 给document添加鼠标移动事件 (mousemove)
  • 获取移动的位置 (e.pageX,e.pageY)
  • 设置对应的拖拽元素的位置 (用页面的位置 - 当前的盒子内点击的位置 当前盒子在页面上的坐标)
  • 给document弹起事件 (mouseup)
  • 取消移动事件及弹起事件 (赋值为null)
<div></div>
<script>
    //获取div
    var div = document.querySelector('div')
    //给div添加鼠标按下事件
    div.onmousedown = function (e) {
        e = e || window.event
        //记录按下的位置 位于按下元素内的位置
        var x = e.offsetX
        var y = e.offsetY
        //给document添加鼠标移动事件
        document.onmousemove = function (e) {
            e = e || window.event
            //用页面的位置 - 当前的盒子内点击的位置 当前盒子在页面上的坐标
            div.style.left = e.pageX - x  + 'px'
            div.style.top = e.pageY - y  + 'px'
        }
        document.onmouseup = function () {
            //取消移动事件及弹起事件
            document.onmousemove = document.onmouseup = null
        }
    }
</script>

局部拖拽思路

实现思路
  • 给需要拖拽的元素添加鼠标按下事件 (mousedown)
  • 记录按下的位置 (记录当前元素内按下的坐标 e.offsetX, e.offsetY)
  • 给外面的大盒子添加鼠标移动事件 (mousemove)
  • 获取移动的位置 (e.pageX,e.pageY)
  • 得到对应的拖拽元素的位置 (鼠标在页面的位置 - 大盒子离页面的位置 - 按下的位置)
  • 区间判断 (不能小于0 不能大于(大盒子的大小-小盒子的大小)的距离)
  • 设置位置
  • 给document弹起事件 (mouseup)
  • 取消移动事件及弹起事件 (赋值为null)
<div class="warp">
	<div class="inner"></div>
</div>
<script>
	var warp = document.querySelector('.warp')
	var inner = document.querySelector('.inner')
	//给需要拖拽的元素添加鼠标按下事件 (mousedown)
	inner.onmousedown = function(e){
		e = e || window.event
		//记录当前元素内按下的坐标
		var x = e.offsetX
		var y = e.offsetY
		//给外层盒子添加移动事件
		warp.onmousemove = function(e){
			e = e || window.event
			//得到对应的拖拽元素的位置 
			var targetX = e.pageX - warp.offsetLeft - x
			var targetY = e.pageY - warp.offsetTop - y
			//区间判断
			if(targetX < 0){
				targetX = 0
			}
			if(targetY < 0){
				targetY = 0
			}
			if(targetX > warp.clientWidth-inner.clientWidth){
				targetX = warp.clientWidth-inner.clientWidth
			}
			if(targetY > warp.clientHeight -inner.clientHeight){
				targetY = warp.clientHeight -inner.clientHeight
			}
			//设置位置
			inner.style.top = targetY + 'px'
			inner.style.left = targetX + 'px'
		}
		//给document添加弹起事件
		document.onmouseup = function(){
			warp.onmousemove = document.onmouseup = null
		}
	}
</script>
拖拽的方法封装
//设计一个方法来计算对应的盒子在页面的位置
function getPointToPage(element) {
    //offset家族
    //offsetParent 偏移的父元素
    //offsetWidth 偏移元素的宽度
    //offsetHeight 偏移元素的高度
    //offsetLeft 基于偏移的父元素的左偏移量
    //offsetTop 基于偏移的父元素的上偏移量
    //如果对应的offsetParent没有值为null的时候停止 element为body
    var point = {
        x: 0,
        y: 0
    }
    while (element.offsetParent) {
        point.x += element.offsetLeft
        point.y += element.offsetTop
        //不断向上
        element = element.offsetParent
    }
    return point
}
//拖拽的方法封装
function drag(dragElement,target) {
    //给需要拖拽的元素添加鼠标按下事件 (mousedown)
    dragElement.onmousedown = function (e) {
        e = e || window.event
        //记录当前元素内按下的坐标
        var x = e.offsetX
        var y = e.offsetY
        //给外层盒子添加移动事件
        target.onmousemove = function (e) {
            e = e || window.event
            //得到对应的拖拽元素的位置 
            var targetX = e.pageX - getPointToPage(target).x - x
            var targetY = e.pageY - getPointToPage(target).y - y
            //区间判断
            if (targetX < 0) {
                targetX = 0
            }
            if (targetY < 0) {
                targetY = 0
            }
            if (targetX > target.clientWidth - dragElement.clientWidth) {
                targetX = target.clientWidth - dragElement.clientWidth
            }
            if (targetY > target.clientHeight - dragElement.clientHeight) {
                targetY = target.clientHeight - dragElement.clientHeight
            }
            //设置位置
            dragElement.style.top = targetY + 'px'
            dragElement.style.left = targetX + 'px'
        }
        //给document添加弹起事件
        document.onmouseup = function () {
            target.onmousemove = document.onmouseup = null
        }
    }
}