最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 使用Vue自定义指令实现右键菜单

    正文概述 掘金(神奇的程序员)   2020-12-05   557

    前言

    浏览器里右键时会有一个默认的菜单,在我的开源项目中正好有自定义右键菜单的需求,在npm库找了下与之相关的包,发现都是以组件形式实现的,感觉那种做法太过繁琐。

    于是,我就想着能不能像vue的内置指令那样,绑定到元素上,在这个元素上右键就能出现右键菜单,这样做就方便很多了。

    看了下vue的自定义指令文档后,经过一番折腾,终于实现我的这个想法,本文就跟大家分享下我的实现思路以及过程,欢迎各位感兴趣的开发者阅读本文。

    实现思路

    Vue中有很多内置指令,例如:v-ifv-forv-model,它除了这些内置指令外,还允许我们开发者自己注册指令,来实现我们想实现的效果,对Vue自定义指令不熟悉的开发者可以先看一下文档:自定义指令。

    接下来,就跟大家讲一下我的实现思路:

    • 布局右键菜单,编写样式

    • 将右键菜单需要的用到的数据在vuex中进行定义

    • 全局注册一个指令,命名为rightClick

    • 拦截被绑定元素的oncontextmenu事件,对组件传过来的值进行处理

    • 更新vuex里的右键菜单数据,触发右键菜单显示

    实现过程

    接下来,就跟大家分享下我的实现过程。

    布局右键样式

    我们先来看看这个组件需要哪些数据才能让其显示在鼠标所点的位置。

    • 它的显隐状态,即:元素css的display属性
    • 它的位置,即:元素css的lefttop属性
    • 它的文本数据,即:右键菜单要展示的内容,通过v-for来渲染
    • 它的事件处理函数,即:右键菜单中选项点击时,要进行的事件处理

    我们在项目中找一个公用组件,确保这个组件会被渲染,在组件的template中加入下述代码。

        <!--右键菜单-->
        <div
          id="rightMenuDom"
          class="right-menu"
          :style="{
            display: rightMenuStatus,
            top: rightMenuTop,
            left: rightMenuLeft
          }"
        >
          <ul>
            <!--分为2组渲染-->
            <li>
              <span
                v-for="item in rightMenuList"
                :key="item.id"
                v-show="item.id <= 3"
                @click="item.handler"
                >{{ item.text }}
              </span>
            </li>
            <li>
              <span
                v-for="item in rightMenuList"
                :key="item.id"
                v-show="item.id > 3"
                @click="item.handler"
                >{{ item.text }}
              </span>
            </li>
          </ul>
        </div>
      </div>
    

    随后,在组件的mounted生命周期中添加全局点击事件的监听,目的是在点击任意位置后隐藏右键菜单。

      mounted() {
        // 监听全局点击事件
        document.addEventListener("click", () => {
          // 隐藏右键菜单
          this.$store.commit("updateRightMenuStatus", {
            status: "none",
            left: "0px",
            top: "0px"
          });
        });
      }
    

    紧接着,在组件的computed中获取Vuex中定义的数据,用于渲染右键菜单。

      computed: {
        // 右键菜单显隐状态
        rightMenuStatus(): string {
          return this.$store.state.rightMenu.status;
        },
        // 右键菜单距离浏览器顶部高度
        rightMenuTop(): string {
          return this.$store.state.rightMenu.top;
        },
        // 右键菜单距离浏览器左边长度
        rightMenuLeft(): string {
          return this.$store.state.rightMenu.left;
        },
        // 右键菜单列表内容
        rightMenuList(): [] {
          return this.$store.state.rightMenu.list;
        }
      }
    

    最后,给它编写css样式。

    // 右键菜单样式
      .right-menu {
        position: fixed;
        left: 0;
        top: 0;
        width: 166px;
        height: auto;
        background-color: rgb(242, 242, 242);
        border: solid 1px #C2C1C2;
        box-shadow: 0 10px 10px #C2C1C2;
        display: none;
        border-radius: 5px;
    
        ul {
          padding: 0;
          margin: 0;
          font-size: 15px;
    
          li {
            list-style: none;
            box-sizing: border-box;
            padding: 6px 0;
            border-bottom: 1px solid rgb(216, 216, 217);
    
            &:nth-child(1) {
              padding-top: 2px;
            }
    
            &:nth-last-child(1) {
              border-bottom: none;
            }
    
            span {
              display: block;
              height: 20px;
              line-height: 20px;
              padding-left: 16px;
    
              &:hover {
                background-color: #0070F5;
                cursor: pointer;
                color: #FFFFFF;
              }
            }
          }
        }
      }
    
    

    在Vuex中定义数据

    在vuex的配置文件中,找到state属性,添加下述代码。

    • status组件的显隐状态
    • top组件距离浏览器可视区域顶部的距离
    • left距离浏览器可视区域左边的距离
    • list组件需要的文本数据和与之对应的事件处理函数
    rightMenu: {
      status: "none",
      top: "0px",
      left: "0px",
      list: []
    }
    

    随后在mutations中添加更新数据的方法。

    // 更新右键菜单数据
    updateRightMenuStatus(state, menuObj: rightMenuAttribute) {
      state.rightMenu.status = menuObj.status;
      state.rightMenu.top = menuObj.top;
      state.rightMenu.left = menuObj.left;
      state.rightMenu.list = menuObj.list;
    }
    

    注册全局指令

    我们在vue的入口文件:main.ts中,注册一个全局指令rightClick

    • el为我们绑定指令的元素
    • binding里包含了指令传过来的参数
    app.directive("rightClick", (el, binding) => {
      
    });
    

    拦截右键事件处理指令参数

    上面我们注册了一个全局指令,我们需要在它的函数内部为指令所绑定的元素重写其点击事件,处理指令传过来的参数。

    • 将事件对象放进一个数组中
    • 将每一个右键菜单的文本数据和与之对应的时间处理函数放进json数组中
    • 获取鼠标点击的位置,使用commit更新Vuex中的相关数据,渲染页面
      el.oncontextmenu = function(e: MouseEvent) {
        const textArray = binding.value.text;
        const handlerObj = binding.value.handler;
        // 事件处理数组
        const handlerArray = [];
        // 处理好的右键菜单
        const menuList = [];
        // 将事件处理函数放入数组中
        for (const key in handlerObj) {
          handlerArray.push(handlerObj[key]);
        }
        // 追加右键菜单数据
        for (let i = 0; i < textArray.length; i++) {
          // 右键菜单对象, 添加名称
          const menuObj = {
            text: textArray[i],
            handler: handlerArray[i],
            id: i + 1
          };
          menuList.push(menuObj);
        }
        // 鼠标点的坐标
        const oX = e.clientX;
        const oY = e.clientY;
        // 右键菜单出现后的位置
        store.commit("updateRightMenuStatus", {
          status: "block",
          left: oX + "px",
          top: oY + "px",
          list: menuList
        });
        return false;
      };
    

    在组件中使用指令

    完成上述操作后,我们就已经实现了右键自定义菜单的指令,接下来,我们来看看如何在组件中使用我们注册的指令。

    在你想要绑定右键菜单的html元素上添加v-right-click,如下所示:

    <li
      class="row-panel"
      v-right-click="rightMenuObj"
    >
    </li>
    

    在组件的data中定义右键菜单需要的数据,即上面代码中声名的rightMenuObj

    // 右键菜单对象,菜单内容和处理事件
    rightMenuObj: {
      text: [
        "查看资料",
        "复制用户id",
        "移除该会话",
        "在联系人中查看",
        "在单聊窗口中打开",
        "会话置顶"
      ],
      handler: {
        checkingData() {
          console.log("查看资料点击事件");
        },
        copyId() {
          console.log("复制用户id点击事件");
        },
        removeItem() {
          console.log("移除会话点击事件");
        },
        showContact() {
          console.log("在联系人中查看");
        },
        showSingleChat() {
          console.log("在单聊窗口中打开");
        },
        topConversation() {
          console.log("会话置顶");
        }
      }
    }
    

    随后,我们就可以运行看效果了,如下所示,已经成功实现了我们想要的效果。

    使用Vue自定义指令实现右键菜单

    代码地址

    本文中演示所用的组件GitHub地址如下:

    msg-list.vue

    main.ts

    main-content.vue

    main-content.scss

    index.ts

    写在最后

    • 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注?
    • 本文首发于掘金,未经许可禁止转载?

    起源地下载网 » 使用Vue自定义指令实现右键菜单

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元