vue3 uses custom right-click to save in jsx and prohibits browser right-click

Effect display: (The style imitates Feishu’s, a relatively simple design that can be adjusted according to needs)

Implementation steps:

1. Define the HTML page structure. Since I use JSX syntax in the script tag, the structure is written in the return of the render function. It is actually simpler if it is in the template. I also give the structure of the template here.

 

{
        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. Write the css code structure. The code here is nothing special. I will pay attention to two points. One is to set the position to fixed for myclick, and the second is to set a higher level for it so that it can be displayed normally. Right-click the div that appears, otherwise it may be covered or not displayed.

.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. Write the method part, mainly the method of opening openMenu, cancellation and event processing in the points. There are two points that need to be paid attention to here, one is the passing in of parameters, and the other is the processing of closing the pop-up window. I will explain it at the end. Let’s talk about these issues in detail and show the code first.

// 自定义右键下载按钮
    // 检测页面滚动就关闭弹窗
    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. Data definition and return:

4.1 Definition of data:

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

4.2 Return of data and methods (cannot be used in template if return is not done)

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

5. Notes on the method:

In fact, there are many plug-ins that can be used. If there is one that meets expectations, you can use it directly. Since I wrote this by myself, it is inevitable to deal with bugs. There are many phenomena that do not meet expectations. I will ask questions below. And the solution:

① After right-clicking, the myclick part will still exist when clicking on other parts. The expectation is that it will be the same as in the browser, and it will disappear when clicking on other parts.

problem solved:

Code part:

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

The idea is to add a click event to the whole world when clicking to open the pop-up window. If the expected part is exceeded, for example, I want to modify the right-click event of the QR code part, and the other parts can be used as usual, so the click event is set for the body for the exceeded part. , the result is to close the pop-up window

②Add @contextmenu.prevent in vue to prevent the default right mouse button event, but the syntax cannot be used normally in jsx

problem solved:

The method of preventing default events is adopted, prohibiting the right mouse button e.preventDefault()

③When changes are detected on the page, or when the screen is scrolling, the pop-up window opened by right-clicking cannot be closed and will always hang there, which greatly affects the operation and is a serious bug.

Code part:

const changeScoll = ()=>{

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

      if (proxy.visible == true) {

        proxy.visible = false

      }

    }

The idea is to monitor the scrolling of the page. Once scrolling occurs in the relevant area, just close the window.

④ Right click on the part that needs to be saved, and a pop-up window pops up at the QR code of the entire cloumn part. This is because if only one visible is bound and controlled using proxy.visible, all will be opened naturally, because each row uses They are all the same variable. Here you need to set a separate ref variable for each row. However, ref variables cannot be defined in jsx. You can only use js statements.

Code part:

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

The idea is to add a ref variable to the basic template. The if condition here is where you need to add it. For example, here is the general table part. Why do I need to judge the condition? Because if it is all added, other parts will be added by default. The basic template I have here is a general template, so I add a visible variable to each row of cloumn in the page that needs to be added to control the two-dimensionality of each small row. The code pop-up window can be displayed. It is worth noting that I process row.visible here to control the pop-up window and also introduce the proxy.visible public variable control. This is because in addition to each small condition, everyone has a common feature. Then it will be closed when the page is scrolled and when the outside is clicked, so a variable can be used to control it, so don't get confused when watching.

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

Supplement: (Personal feeling may be wrong)

I feel that jsx is mainly related to react. Although the boss who led me said that it has little to do with it, when I search for related questions, most of the pop-ups are related to react, because the main development language I currently use is vue, and the react I learned at the beginning is relatively I have almost forgotten the basics. I will learn a review of react later when I am not busy. Then there will be an article to fix the pitfalls. The predicted title should be the points that need to be paid attention to when using jsx in vue and react.

Guess you like

Origin blog.csdn.net/weixin_54515240/article/details/129386147