JavaScript前端那些事儿Web前端之路

2017百度前端技术学院-自定义右键菜单

2017-02-24  本文已影响1368人  起这么长的名字根本没有用

效果预览
源码地址

一、事件流

1、冒泡

示例:

html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义右键菜单</title>
</head>
<body>
    <ul id='menu'>
        <li>menu item 1</li>
        <li>menu item 2</li>
    </ul>
</body>
</html>

js

document.oncontextmenu =function (){
    alert('触发了);
}

效果

2、捕获

标准的监听事件方式(标准浏览器都可使用,IE9以上)

    element.addEventListener(eventType, fn, false) 
说明:

IE下的监听事件方式(IE专有)

·attachEvent(eventType,fn)· IE专有。

说明:

此种监听方式只有冒泡没有捕获。

注意:
     document.addEventlistener('contextmenu',function (){
     alert('我是标准的我不需要on')
   },false)
    document.attachEvent('oncontextmenu',function(){
             alert('我是IE的我需要on')
    })

一般使用标准即可,如果兼容IE 8以下再考虑第二种,做兼容方式的书写。

二、oncontextmenu

属于鼠标事件,鼠标右键点击即触发。

用法:

我在document上绑定了此事件,通过事件冒泡机制触发。

document.oncontextmenu =function (){
    alert('触发了);
}

3、事件对象event

概念:

Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。
事件通常与函数结合使用,函数不会在事件发生前被执行

        document.addEventlistener('contextmenu',function(ev){
             alert(ev)
    })
        document.attachEvent('onc ontextmenu',function(){
             alert(window.event)
    })

一般如果不兼容ie 8以下,用标准下的event即可

4、取消默认行为

event.preventDefault()

5、阻止冒泡

event.stopPropagation()

说明:

return false既可以阻止默认行为,也可以阻止冒泡

6、获取滚动距离

document.body.scrollTop(scrollLeft)

document.documentElement.scrollTop(scrollLeft)

      var scrollTop = document.documentElement.scrollTop||document.body.scrollTop,
        var scrollLeft = document.documentElement.scrollLeft||document.body.scrollLeft,

7、clientX(Y)

它提供事件发生时的应用客户端区域的水平坐标 (与页面坐标不同)。例如,当你点击客户端区域的左上角时,鼠标事件的 clientX 值为 0 ,这一值与页面是否有水平滚动无关

也就是说到浏览器可视窗口的距离(不包括浏览器的工具栏)

8、 获取元素具体尺寸

通常,元素的offsetHeight是一种衡量标准,包括元素的边框、垂直(水平)内边距和元素的水平(垂直)滚动条(如果存在且渲染的话)和元素的CSS高度(宽度)

注意:

clientWidth/clientHeight的区别是,`clientWidth/clientHeight 不包括边框,和垂直(水平)滚动条的宽度(高度)

9、获取浏览器视口的尺寸

    var   browserHeight = document.documentElement.clientHeight,//浏览器视口的高度
                    browserWidth = document.documentElement.clientWidth; 
注意:

一开始使用了window.innerWidth/window.innerHeight 来获取视口尺寸,结果在极限情况下被滚动条覆盖一部分,后来找到原因是:window.innerWidth/window.innerHeight 是把滚动条也算在内的

10、类数组转换成数组

Array.prototype.slice.call(类数组,0)

11、自定义右键菜单实现思路

1、让自定义菜单相对于浏览器视口做绝对定位通过改变left/top值来改变每次菜单的位置
2、取消原来的右键菜单默认行为
3、考虑极限情况,判断event.clientX+菜单的offsetWidth/event.clientY+offsetHeight是否大于等于 document.documentElement.clientWidth/document.documemtElement.clientHeight ,如果大于等于,则把left/top赋值为event.clientX-菜单的offsetWidth/event.clientY-菜单的offsetHeight,否则赋值为event.clientX/event.clientY

js代码:
    window.onload = function (){
  var oClick = document.getElementById('click_region'),
      oMenu = document.getElementById('menu'),
      aLi = oMenu.getElementsByTagName('li'),
      browserHeight = document.documentElement.clientHeight,//浏览器视口的高度
      browserWidth = document.documentElement.clientWidth; //浏览器视口的快读,不包括垂直滚动天的宽度

  document.oncontextmenu = function (ev){
    oMenu.style.display = 'block';
    var ev = ev||window.event,
        scrollTop = document.documentElement.scrollTop||document.body.scrollTop,
        scrollLeft = document.documentElement.scrollLeft||document.body.scrollLeft,
        clientX = ev.clientX,
        clientY = ev.clientY,
        // 注意:只有在隐藏的元素变成display:block的状态才能获取他的宽度和高度
        offsetWidth = oMenu.offsetWidth,
        offsetHeight = oMenu.offsetHeight,
        top,
        left;

    if(clientY+offsetHeight>=browserHeight){
       top = clientY-offsetHeight
    }else{
      top = clientY
    }

    if(clientX+offsetWidth>=browserWidth){
      left = clientX-offsetWidth
      console.log(left);
    }else{
      left = clientX
    }

    oMenu.style.left = left+'px';
    oMenu.style.top =scrollTop+top+'px';
    return false//阻止默认行为,并且阻止冒泡
  }

  // 取消自定义菜单
  document.onclick = function (){
      oMenu.style.display = 'none';
  }

    var lis = Array.prototype.slice.call(aLi,0); //类数组转成数组


    //遍历数组
    lis.forEach(function (item,index,arr){
      aLi[index].onclick = function (event){
        alert(this.innerHTML)
         event.stopPropagation();
      }
    })

}
上一篇 下一篇

猜你喜欢

热点阅读