vue3 在jsx中使用自定义右键保存,禁止游览器右键

效果展示:(样式模仿飞书的,较为简单的设计,可以根据需求调整)

实现步骤:

1.定义HTML页面结构,由于我是在script标签中使用了JSX语法,所以结构写在render函数的return里面,如果在template里面其实更简单,我这里也给出template的结构

{
        label: "商品e-ID",
        prop: "eid",
        render: row => {
          let QRcodeName = row.eid + "-" + row.version
          let clickstyle = 'left:'+proxy.left+'px'+';'+'top:'+proxy.top+'px'
          // console.log(clickstyle)
          // console.log(row.visible,969696)
          if (!row.eidQrcode.smallImageUrl) return (<el-button onClick={() => proxy.makeQRcode(row)} type="text" >点击生成</el-button>)
          return (
            <div class="Ercode" onClick={() => proxy.cancelMenu(row)}  onContextmenu={() => {proxy.openMenu(event,row)}} style="width:60px;margin:0 auto;">
              <el-image
                style="width:60px;height:60px;margin-right:5px;"
                fit="cover"
                src={row.eidQrcode.smallImageUrl}
                preview-src-list={[row.eidQrcode.imageUrl]}
              />
              <div class="myclick"  v-show={row.visible && proxy.visible} style={clickstyle} >
                  <ul>
                      <li onClick={() => proxy.downloadthis(row)}>保存</li>
                      <li onClick={() => proxy.cancelMenu(row)}>取消</li>
                  </ul>
              </div>
            </div>
          )
        }
      },
<div class="mask" @click="cancelMenu"  @contextmenu.prevent="openMenu($event)">

   

  </div>

  <div class="myclick"  v-show="visible" :style="{'left':left+'px','top':top+'px'}" >

    <ul  class="contextmenu">

        <li @click="downloadthis">另存为</li>

        <li @click="cancelMenu">取消</li>

    </ul>

  </div> 

 2.编写css代码结构,这里的代码没什么特别的,我将两个需要注意的点,一个是需要为myclick设置position为fixed,第二就是为他设置一个较高的层级,这样就能正常显示右键出现的div,不然可能会被遮住或者不显示。

.mask {
  position: relative;
  width:240px;
  height:70px;
  background:skyblue
}
.myclick {
  position: fixed;
  z-index: 99999;
  width:120px;
  height:60px;
  background:white;
  border-radius: 5px;
}
.myclick li {
  list-style: none;
  /* padding-left: 4px; */
  margin: 4px;
  border-radius: 5px;
  color: #1F2329;
}
.myclick li:hover {
  background-color: #EDEEEE;
  margin: 4px;
}

3.编写方法部分,主要是打开openMenu的方法和取消以及点中的事件处理,这里需要注意的也有两个点,一个是参数的传入,一个是弹窗关闭的处理,我会在结尾处细讲这些问题,先展示代码

// 自定义右键下载按钮
    // 检测页面滚动就关闭弹窗
    const changeScoll = ()=>{
      // console.log("检测到滚动了嘛?")
      if (proxy.visible == true) {
        proxy.visible = false
      }
    }
    const openMenu = (e,row)=> {
      console.log("点击了替换后的鼠标右键函数!")
      if (!proxy.visible){
        proxy.visible = true
      }else{
          document.body.addEventListener("click",function(){
          // console.log("必须在界面外部点击后移除 不然会很大bug")
          proxy.visible = false
        })
      }
      e.preventDefault()
      var x = e.pageX;
      var y = e.pageY;
      proxy.top = y;
      proxy.left = x;
      // let body = document.querySelector("body")
      // body.onClick = function(row){
      //   console.log("绑定上了吗?")
      //   row.visible=false
      // }
      row.visible = true;//在这里控制右键菜单的打开
    }
    const cancelMenu = (row)=>{
      if (row.visible == true){
        console.log("取消点击")
        row.visible = false;
      }
    }
    const downloadthis =(row) => {
      console.log("选中点击")
      let QRcodeName = row.eid + "-" + row.version
      proxy.download(row.eidQrcode.imageUrl, QRcodeName)
      row.visible = false;
    }
    // 自定义右键下载按钮

 4.数据的定义以及返回:

4.1数据的定义:

// 新调整,自定义右键下载按钮
    const scrollTop = ref(0)
    const visible = ref(true)
    const top=ref(0)
    const left = ref(0)

4.2数据以及方法的return(如果不做return不能在template中使用)

return {
      // 自定义右键下载按钮
      changeScoll,
      cancelMenu,
      downloadthis,
      visible,
      openMenu,
      // 自定义右键下载按钮
}

5.方法的注意点:

其实也有比较多的插件可以使用,如果有符合预期的可以直接使用,由于我这个是自己写的,所以不可避免的就是bug的处理,有着较多的不符合预期现象产生,下面我分别提出问题以及解决:

①点击右键后,点击其他部分myclick部分依旧存在,预期是希望能够和游览器中的一样,点击其他部分就消失

问题解决:

代码部分:

if (!proxy.visible){
        proxy.visible = true
      }else{
          document.body.addEventListener("click",function(){
          // console.log("必须在界面外部点击后移除 不然会很大bug")
          proxy.visible = false
        })
      }

思路是当点击打开弹窗的时候,为全局添加一个点击事件,如果超出了预期部分,比如我这里就是希望修改二维码部分的右键事件,其他部分照常使用,所以超出部分为body设置点击事件,结果是关闭弹窗

②在vue中添加@contextmenu.prevent即可阻止默认的鼠标右键的事件,但是语法无法在jsx中正常使用

问题解决:

采用了阻止默认事件的方法,禁止鼠标右键e.preventDefault()

③当页面发现变化后,或者说屏幕滚动的时候,右键打开的弹窗不能关闭会一直挂在那里,非常影响操作,较为严重的bug

代码部分:

const changeScoll = ()=>{

      // console.log("检测到滚动了嘛?")

      if (proxy.visible == true) {

        proxy.visible = false

      }

    }

思路就是监视页面的滚动,一旦相关区域发生了scroll滚动的话就即使关闭视窗就可以了

④右键需要保存部分,整个cloumn部分的二维码处都弹出来了弹窗,这是因为如果只绑定了一个visible,使用proxy.visible控制,自然就会全部打开,因为每一个row用的都是同一个变量,这里需要为每一个row设置单独的ref变量,但是jsx中无法定义ref变量,只能使用js语句

代码部分:

 if (data.records[0].devStatus){
              item.visible = ref(false)
            })
            }

思路是在basic模板的地方加入一个ref变量,这里的if条件就是你需要加入的地方比如我这里是总表部分,为什么需要判断条件呢?因为如果是全加的话其他部分也会默认加上,我这里的basic模板是一个通用模板,所以在需要加入的页面中的cloumn的每一个row加入一个visible变量来控制每一个小row的二维码弹窗的展示即可,值得注意的是我这里处理row.visible来控制弹窗还引入了proxy.visible公共变量控制,这里是因为除了每个小条件以外,大家都有一个公共的特点,那就当页面滚动的时候和点击外部的时候关闭,所以这里可以使用一个变量来控制,所以看的时候不要搞混了。

 <div class="myclick" v-show的控制用了两个变量 v-show={row.visible && proxy.visible} style={clickstyle} >
                  <ul>
                      <li onClick={() => proxy.downloadthis(row)}>保存</li>
                      <li onClick={() => proxy.cancelMenu(row)}>取消</li>
                  </ul>
              </div>

补充:(个人感觉可能有错)

我感觉jsx主要还是和react相关,虽然带我的大佬说关系不大,但是我搜索相关问题的时候弹出大多都是react相关,因为我目前主要用的开发语言是vue,当初学的react比较基础也忘的差不多了,后续在业务不忙的时候学习一个回顾react,到时候会出一个补坑的文章,预测标题应该是vue和react中使用jsx需要的注意点。

猜你喜欢

转载自blog.csdn.net/weixin_54515240/article/details/129386147