当前位置:主页 > 网页前端 > vue >

vue自定义封装指令以及实际使用

时间:2022-09-05 10:55:05 | 栏目:vue | 点击:

前言

vue默认内置了v-model、v-if、v-show、v-html、v-text等指令,但是这些往往不足以满足我们实际项目开发中的场景,比如权限控制按钮、路由菜单,复制文字等功能,就需要我们自己自定义一些满足我们项目需求的指令了,那怎么封装自定义指令,并使用呢?我们先从封装指令的基础说起。

封装指令基础

钩子函数

钩子函数参数

钩子函数参数包含了el、binding、vnode、oldVnode。

实际使用

复制指令(v-copy)

我们先看如何使用:

单击复制

<div v-copy>单击复制</div> // 默认复制div的文案
<div v-copy="copyStr">单击复制</div> // 复制指令里的内容(copyStr)

给el添加点击事件,判断binding的value值是否为空,若为空,默认获取绑定元素的文本内容

el.addEventListener("click", () => {
    let str = binding.value ? binding.value : el.innerText;

    handleClick(str);
});
el.style.cursor = "copy";

双击复制

<div v-copy:dblclick>双击复制</div> // 默认复制div的文案
<div v-copy:dblclick="copyStr">双击复制</div> // 复制指令里的内容(copyStr)

给el添加双击事件,判断binding的value值是否为空,若为空,默认获取绑定元素的文本内容

el.addEventListener("dblclick", () => {
    let str = binding.value ? binding.value : el.innerText;

    handleClick(str);
});
el.style.cursor = "copy";

点击icon复制

<div v-copy:icon>单击icon复制</div> // 默认复制div的文案
<div v-copy:icon="copyStr">单击icon复制</div> // 复制指令里的内容(copyStr)

判断el是否已经增加了icon,没有则增加i标签,放置icon,给icon增加点击事件,进行复制

if (el.hasIcon) return;

const iconElement = document.createElement("i");

iconElement.setAttribute("class", "el-icon-document-copy");
iconElement.setAttribute("style", "margin-left:5px");
el.appendChild(iconElement);
el.hasIcon = true;
iconElement.addEventListener("click", () => {
    let str = binding.value ? binding.value : el.innerText;

    handleClick(str);
});
iconElement.style.cursor = "copy";

handleClick 逻辑

判断是否有id为copyTarget的输入框,没有则创造一个id为copyTarget的输入框,然后进行选中,调用execCommand('copy')进行选中文字的复制。

function handleClick (text) {
    if (!document.getElementById("copyTarget")) {
        const copyTarget = document.createElement("input");

        copyTarget.setAttribute("id", "copyTarget");
        copyTarget.setAttribute("style", "position:fixed;top:0;left:0;opacity:0;z-index:-1000;");
        document.body.appendChild(copyTarget);
    }

    // 复制内容
    const input = document.getElementById("copyTarget");

    input.value = text;
    input.select(); // 选取文本域中的内容。
    // 调用execCommand()可以实现浏览器菜单的很多功能. 如保存文件,打开新文件,撤消、重做操作…
    document.execCommand("copy"); // 复制选中的文字到剪贴板;
    // Message.success("复制成功");
    Notification({
        title: "成功",
        message: `${text}已复制到剪切板`,
        type: "success"
    });
}

完整代码

import { Message, Notification } from "element-ui";

function handleClick (text) {
    if (!document.getElementById("copyTarget")) {
        const copyTarget = document.createElement("input");

        copyTarget.setAttribute("id", "copyTarget");
        copyTarget.setAttribute("style", "position:fixed;top:0;left:0;opacity:0;z-index:-1000;");
        document.body.appendChild(copyTarget);
    }

    // 复制内容
    const input = document.getElementById("copyTarget");

    input.value = text;
    input.select(); // 选取文本域中的内容。
    // 调用execCommand()可以实现浏览器菜单的很多功能. 如保存文件,打开新文件,撤消、重做操作…
    document.execCommand("copy"); // 复制选中的文字到剪贴板;
    // Message.success("复制成功");
    Notification({
        title: "成功",
        message: `${text}已复制到剪切板`,
        type: "success"
    });
}

const install = function (Vue) {
    Vue.directive("copy", {
        bind (el, binding) {
            if (binding.arg === "dblclick") { // 双击触发
                el.addEventListener("dblclick", () => {
                    let str = binding.value ? binding.value : el.innerText;

                    handleClick(str);
                });
                el.style.cursor = "copy";
            } else if (binding.arg === "icon") { // 点击icon触发
                if (el.hasIcon) return;

                const iconElement = document.createElement("i");

                iconElement.setAttribute("class", "el-icon-document-copy");
                iconElement.setAttribute("style", "margin-left:5px");
                el.appendChild(iconElement);
                el.hasIcon = true;
                iconElement.addEventListener("click", () => {
                    let str = binding.value ? binding.value : el.innerText;

                    handleClick(str);
                });
                iconElement.style.cursor = "copy";
            } else { // 单击触发
                el.addEventListener("click", () => {
                    let str = binding.value ? binding.value : el.innerText;

                    handleClick(str);
                });
                el.style.cursor = "copy";
            }
        }
    });
};

export default install;

权限操作指令(v-hasPermi)

import store from "@/store";

const allPermission = "*:*:*";
export function hasPermi(value){
    // return true;
    const permissions = store.getters && store.getters.permissions;
    if (value && value instanceof Array && value.length > 0) {
        const permissionFlag = value;
        const hasPermissions = permissions.some(permission => allPermission === permission || permissionFlag.includes(permission));
        if (!hasPermissions) {
            return false;
        }
        return true;
    }
    throw new Error("请设置操作权限标签值");
}


export default {
    inserted(el, binding) {
        const { value } = binding;
        if (!hasPermi(value)){
            el.parentNode && el.parentNode.removeChild(el);

        }
    }
};

总结

您可能感兴趣的文章:

相关文章