当前位置 主页 > 网站技术 > 代码类 >

    分别使用vue和Android实现长按券码复制功能

    栏目:代码类 时间:2019-11-12 12:02

    最近分别用vue和Android实现了一个券码复制功能,长按券码会在上方弹出一个拷贝的icon提示,点击icon将券码内容复制到剪贴板。现将一些经验代码分享给大家以供参考。废话不多说,先上效果图

    在这里插入图片描述

    vue实现:

    npm install clipboard --save

    <div class="coupon-count-container" @click="closePopBubble">
     <ul>
      <li v-for="(couponItem, index) in couponArray" :key="index">
       <div class="coupon-code-item">
        <img class="pop-bubble-copy" : src="../../assets/couponPayResult/copy_icon.png" @click="copyToClipboard($event, couponArray[clickedIndex].codeNo)">
        <span class="code-label">券码:</span><span class="code-active" v-tap="{longMethod: getPopBubble, params: index}">{{couponItem.codeNo}}</span>
       </div>
      </li>
     </ul>
    </div>
    data: function() {
     return {
      couponArray: [],
      showPopBubble: false,
      x: 0,
      y: 0,
      clickedIndex: 0
     }
    }
    
    .coupon-code-item {
     position: relative;
     padding: 10px 0;
     font-size: 13px;
    }
    
    .pop-bubble-copy {
     position: absolute;
     width: 73px;
     height: 39px;
    }
    
    .code-label {
     margin-left: 28px;
     margin-right: 26px;
     color: #989898;
    }
    
    .code-active {
     color: $color-ff5532;
    }
    
    methods: {
     closePopBubble() {
      if (this.showPopBubble) {
       this.showPopBubble = false;
      }
     },
     getPopBubble(e, index) {
      this.showPopBubble = true;
      this.clickedIndex = index;
      // 对x,y的计算结果进行微调
      this.x = e.target.offsetLeft + 30;
      this.y = e.target.offsetTop - 40;
     },
     copyToClipboard(e, text) {
      this.showPopBubble = false;
      var clipboard = new Clipboard(e.target, {text: () => text.replace(/\s/g, "")});
      clipboard.on('success', e => {
       // 释放内存
       clipboard.off('error');
       clipboard.off('success');
       clipboard.destroy();
      });
      clipboard.on('error', e => {
       // 释放内存
       clipboard.off('error');
       clipboard.off('success');
       clipboard.destroy();
      });
      clipboard.onClick(e);
     }
    }

    实现原理是将气泡弹窗设置为绝对定位,根据券码的位置来计算气泡弹窗相对于父元素的位置,其中父元素为每一条item的包裹元素coupon-code-item

    本次的实现难点是需要自己手动定义vue的长按点击事件:

    Vue.directive('tap',{
     bind:function(el,binding){
      var startTx, startTy,endTx,endTy,longClick,timeOutEvent,
      longMethod=binding.value.longMethod,
      method = binding.value.method,
      params = binding.value.params,
      propagation=binding.value.propagation;
      el.addEventListener("touchstart",function(e){
       var touch=e.touches[0];
       startTx = touch.clientX;
       startTy = touch.clientY;
       if(longMethod && typeof longMethod==='function'){
        longClick=0;
        timeOutEvent =setTimeout(function(){
        longClick=1;
        longMethod(e, params);
        },500)
       }
       if(!propagation){
        if (e.stopImmediatePropagation) {
        e.stopImmediatePropagation();
        } else {
         e.propagationStopped = true;
        }
       }
      },false );
      el.addEventListener("touchmove",function(e){
       if(longMethod && timeOutEvent){
       clearTimeout(timeOutEvent);
       timeOutEvent = 0;
       }
      },false);
      el.addEventListener("touchend",function(e){
       var touch = e.changedTouches[0];
       endTx = touch.clientX;
       endTy = touch.clientY;
       if(longMethod && timeOutEvent){
        clearTimeout(timeOutEvent);
       }
       if((timeOutEvent!=0 && longClick==0)||!longMethod){
        if( Math.abs(startTx - endTx) < 6 && Math.abs(startTy - endTy) < 6){
        if(params instanceof Array){
         method(...params);
        }
        else method(params);
        }
        var focusInput=document.querySelector('input:focus');
        if(focusInput)focusInput.blur();
        var tagName=el.tagName.toLowerCase();
        if(tagName==='input'||tagName==='textarea')el.focus();//获取焦点
        if(!propagation){
        if (e.stopImmediatePropagation) {
         e.stopImmediatePropagation();
        } else {
         e.propagationStopped = true;
        }
        e.stopPropagation();
        return false;
        }
       }
      },false);
     }
    })