[vue] Custom commands to achieve copy, long press, watermark functions


foreword

In vue, in addition to the default built-in directives ( v-model and v-show ) of the core functions, vue also allows registration of custom directives. Its value lies in the fact that developers need to operate on ordinary DOM elements in certain scenarios.

Vue custom directives have two ways of global registration and local registration. Let’s take a look at the way to register global directives first. Register global directives through Vue.directive( id, [definition] ). Then make a Vue.use() call in the entry file.


提示:以下是本篇文章正文内容,下面案例可供参考

1. Create a new folder

Before starting, sort out the directory structure. Create a new directory directives to store custom instructions, among which

  • index.js is the main file of directives, and it is also registered globally
  • copy.js for copying
  • longpress.js is used to implement long press
  • waterMarker.js is used to realize the watermark function

Screenshot of directory structure

insert image description here

2. Create a new file

After creating the directory in the above steps, start to create specific files according to the directory structure, first

directives -> index.js

import copy from "./copy";
import longpress from "./longpress";
import waterMarker from "./waterMarker";
// 自定义指令
const directives = {
    
    
  copy,
  longpress,
  waterMarker,
};

export default {
    
    
  install(Vue) {
    
    
    Object.keys(directives).forEach((key) => {
    
    
      Vue.directive(key, directives[key]);
    });
  },
};

1、v-copy

need:

Realize one-click copying of text content for pasting with the right mouse button.

Ideas:

  • Dynamically create textarea tags, set the readOnly attribute and move out of the visible area

  • Assign the value to be copied to the value attribute of the textarea tag and insert it into the body

  • Select the value textarea and copy

  • Remove the textarea inserted in the body

  • Bind event on first call, remove event on unbind

copy.js
const copy = {
    
    
  bind(el, {
     
      value }) {
    
    
    el.$value = value;
    el.handler = () => {
    
    
      if (!el.$value) {
    
    
        // 值为空的时候,给出提示。可根据项目UI仔细设计
        console.log("无复制内容");
        return;
      }
      // 动态创建 textarea 标签
      const textarea = document.createElement("textarea");
      // 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域
      textarea.readOnly = "readonly";
      textarea.style.position = "absolute";
      textarea.style.left = "-9999px";
      // 将要 copy 的值赋给 textarea 标签的 value 属性
      textarea.value = el.$value;
      // 将 textarea 插入到 body 中
      document.body.appendChild(textarea);
      // 选中值并复制
      textarea.select();
      const result = document.execCommand("Copy");
      if (result) {
    
    
        console.log("复制成功"); // 可根据项目UI仔细设计
      }
      document.body.removeChild(textarea);
    };
    // 绑定点击事件,就是所谓的一键 copy 啦
    el.addEventListener("click", el.handler);
  },
  // 当传进来的值更新的时候触发
  componentUpdated(el, {
     
      value }) {
    
    
    el.$value = value;
  },
  // 指令与元素解绑的时候,移除事件绑定
  unbind(el) {
    
    
    el.removeEventListener("click", el.handler);
  },
};

export default copy;
v-copy copy using

vue single file

<template>
  <button v-copy="copyText">复制</button>
</template>

<script> export default {
    
    
    data() {
    
    
      return {
    
    
        copyText: 'a copy directives',
      }
    },
  }
</script>

2、v-longpress

need:

To implement a long press, the user needs to press and hold the button for a few seconds to trigger the corresponding event

Ideas:

  • Create a timer and execute the function after 2 seconds

  • The mousedown event is fired when the user presses the button, starting the timer; the mouseout event is called when the user releases the button.

  • If the mouseup event is triggered within 2 seconds, clear the timer as a normal click event

  • If the timer is not cleared within 2 seconds, it is judged as a long press and the associated function can be executed.

  • On the mobile side, touchstart and touchend events should be considered

longpress.js
const longpress = {
    
    
  bind: function (el, binding, vNode) {
    
    
    if (typeof binding.value !== "function") {
    
    
      throw "callback must be a function";
    }
    // 定义变量
    let pressTimer = null;
    // 创建计时器( 2秒后执行函数 )
    let start = (e) => {
    
    
      if (e.type === "click" && e.button !== 0) {
    
    
        return;
      }
      if (pressTimer === null) {
    
    
        pressTimer = setTimeout(() => {
    
    
          handler();
        }, 2000);
      }
    };
    // 取消计时器
    let cancel = (e) => {
    
    
      if (pressTimer !== null) {
    
    
        clearTimeout(pressTimer);
        pressTimer = null;
      }
    };
    // 运行函数
    const handler = (e) => {
    
    
      binding.value(e);
    };
    // 添加事件监听器
    el.addEventListener("mousedown", start);
    el.addEventListener("touchstart", start);
    // 取消计时器
    el.addEventListener("click", cancel);
    el.addEventListener("mouseout", cancel);
    el.addEventListener("touchend", cancel);
    el.addEventListener("touchcancel", cancel);
  },
  // 当传进来的值更新的时候触发
  componentUpdated(el, {
     
      value }) {
    
    
    el.$value = value;
  },
  // 指令与元素解绑的时候,移除事件绑定
  unbind(el) {
    
    
    el.removeEventListener("click", el.handler);
  },
};

export default longpress;
v-longpress Long press to use

vue single file

<template>
  <button v-longpress="longpress">长按</button>
</template>

<script> 
export default {
    
    
  methods: {
    
    
    longpress () {
    
    
      alert('长按指令生效')
    }
  }
} 
</script>

3、vue-waterMarker

Requirement: Add a background watermark to the entire page

Ideas:

  • Use the canvas feature to generate image files in base64 format, and set their font size, color, etc.

  • Set it as a background image to achieve a page or component watermark effect

waterMarker.js
function addWaterMarker(str, parentNode, font, textColor) {
    
    
  // 水印文字,父元素,字体,文字颜色
  var can = document.createElement("canvas");
  parentNode.appendChild(can);
  can.width = 200;
  can.height = 150;
  can.style.display = "none";
  var cans = can.getContext("2d");
  cans.rotate((-20 * Math.PI) / 180);
  cans.font = font || "16px Microsoft JhengHei";
  cans.fillStyle = textColor || "rgba(180, 180, 180, 0.3)";
  cans.textAlign = "left";
  cans.textBaseline = "Middle";
  cans.fillText(str, can.width / 10, can.height / 2);
  parentNode.style.backgroundImage = "url(" + can.toDataURL("image/png") + ")";
}

const waterMarker = {
    
    
  bind: function (el, binding) {
    
    
    addWaterMarker(
      binding.value.text,
      el,
      binding.value.font,
      binding.value.textColor
    );
  },
};

export default waterMarker;
v-waterMarker watermark use

vue single file

<template>
  <div v-waterMarker="{text:'amoureux555版权所有',textColor:'rgba(180, 180, 180, 0.4)'}"></div>
</template>
<style scoped>
div{
    
    
  height: 800px;
}
</style>
watermark renderings

insert image description here


Summarize

The commands that need to be used are imported as needed, and the ones imported in index.js can be commented out if not needed, 注意: comment 两个the place!

get off work~

Guess you like

Origin blog.csdn.net/qq_46123200/article/details/129574279