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

效果预览
源码地址

一、事件流

1、冒泡

  • 什么是事件冒泡
    官方的定义就是从最特定的事件目标到最不特定的事件目标。
    意思就是说,假如用户单击了一个元素,该元素拥有一个click事件,那么同样的事件也将会被它的祖先触发,这个事件从该元素开始一直冒泡到DOM树的最上层,这一过程称为事件冒泡

示例:

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、捕获

  • 什么是事件捕获
    事件捕获和事件是相反的,也就是说,当用户触发了一个事件的时候,这个事件是从DOM树的最上层开始触发一直到捕获到事件源.

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

    element.addEventListener(eventType, fn, false) 
说明:
  • 第一个参数: eventType:事件类型
  • 第二个参数:fn 触发的回调函数
  • 第三个参数:一个布尔值,表示冒泡还是捕获。false表示冒泡,true表示捕获

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

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

说明:

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

注意:
  • 标准监听方式不需加on
     document.addEventlistener('contextmenu',function (){
     alert('我是标准的我不需要on')
   },false)
  • IE监听事件方式必须加on
    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)
    })
  • 低版本的IE作为window对象的一个属性
        document.attachEvent('onc ontextmenu',function(){
             alert(window.event)
    })

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

4、取消默认行为

event.preventDefault()

5、阻止冒泡

event.stopPropagation()

说明:

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

6、获取滚动距离

  • chrome:

document.body.scrollTop(scrollLeft)

  • 非chrome:

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/offsetWidth

通常,元素的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();
      }
    })

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • 前言 2017-百度前端技术学院编码任务:自定义网页右键菜单 任务目的 了解js中的oncontextmenu事件...
    朋友喜欢叫我春哥阅读 950评论 0 2
  • 事件流 IE和Netscape开发团队提出了完全相反的两种事件流的概念,事件冒泡流和事件捕获流。 事件冒泡 事件由...
    exialym阅读 887评论 0 9
  • 我们首先要明白,我们给页面添加效果用到的js到底是什么?js其实包含三部分:dom 文档对象模型 bom 浏览...
    一直以来都很好阅读 766评论 0 0
  • 事件流: 事件流:页面接收事件的顺序。 IE定义的:事件冒泡流(由最具体的元素依次传播到DOM树的最上层的Docu...
    xiaoguo16阅读 554评论 0 0
  • ​ 日本是美式复古文化的推手之一,在将美式复古本土化的过程中还创造了个词叫阿美咔叽,意思是美式休闲。日本这个民族怎...
    丹宁说阅读 9,885评论 0 0