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

目录
  • 前言
  • 封装指令基础
    • 钩子函数
    • 钩子函数参数
  • 实际使用
    • 复制指令(v-copy)
      • 单击复制
      • 双击复制
      • 点击icon复制
      • handleClick 逻辑
      • 完整代码
  • 权限操作指令(v-hasPermi)
  • 总结

前言

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

封装指令基础

钩子函数

  • bind:只调用一次,指令第一次绑定到元素时调用。可以进行一次性初始化设置。
  • inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已经被插入文档中)。
  • update:所在组件的VNode更新时调用,也可能发生在其子VNode更新之前。
  • componentUpdated:指令所在组件的VNode及其子VNode全部更新后调用。
  • unbind:只调用一次,指令与元素解绑时调用。

钩子函数参数

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

  • el:指令所绑定的元素,可以用来直接操作DOM。
  • binding:一个对象,包含以下属性
    • name:指令名。不包括v-前缀(如:v-copy的name为copy)。
    • value:指令的绑定值(如:v-copy='1 + 1'中,value值为2)。
    • oldValue:指令绑定的前一个值,仅在update和componentUpdated钩子函数中可用,无论值是否改变都可用。
    • expression:字符串形式的指令表达式(如:v-copy='1 + 1',表达式为"1 + 1")。
    • arg:传给指令的参数(如:v-copy:dblclick中,arg的值为dblclick)。
    • modifiers:一个包含修饰符的对象(如:v-copy.dblclick.icon中,修饰符对象为:{dblclick: true, icon: true})。
  • vnode:Vue编译生成的虚拟节点。
  • oldVnode:上一个虚拟节点。仅在update和componentUpdated钩子函数中可用。

实际使用

复制指令(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)

  • 使用:<el-button v-hasPermi="['activity:school:add']">新增活动</el-button>
  • 从store获取用户的权限数组,判断此时binding的value值是否存在权限数组中,没有则进行按钮的隐藏。
  • 完整代码
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);

        }
    }
};

总结

到此这篇关于vue自定义封装指令以及实际使用的文章就介绍到这了,更多相关vue自定义封装指令内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Vue自定义指令封装节流函数的方法示例

    节流函数是web前端开发中经常用到的一个开发技巧,在input实时搜索,滚动事件等,为了避免过多消耗性能,我们都会使用节流函数.在<JavaScript高级程序设计>一书中有这样的一个例子: function throttle (method, context) { clearTimeout((method.tId)) method.tId = setTimeout(function () { method.call(context) }, 100) } function resizeDiv

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

    目录 前言 封装指令基础 钩子函数 钩子函数参数 实际使用 复制指令(v-copy) 单击复制 双击复制 点击icon复制 handleClick 逻辑 完整代码 权限操作指令(v-hasPermi) 总结 前言 vue默认内置了v-model.v-if.v-show.v-html.v-text等指令,但是这些往往不足以满足我们实际项目开发中的场景,比如权限控制按钮.路由菜单,复制文字等功能,就需要我们自己自定义一些满足我们项目需求的指令了,那怎么封装自定义指令,并使用呢?我们先从封装指令的基础

  • lottie实现vue自定义loading指令及常用指令封装详解

    目录 一.前言 二.实现方式 1.v-loading 2.v-click-outside 三.后记 一.前言 本文主要介绍使用lottie动画实现vue自定义loading的指令方法.另外本篇文章还会介绍其他几个常用的自定义指令实现方式(点击指定区域外监听指令). lottie是一款由airbnb开源的跨平台动画渲染库,支持Android,iOS,Web,Windows平台.是专门用于解析从AE(Adobe After Effects)中通过Bodymovin插件导出的JSON文件,直接渲染动画

  • Vue自定义弹窗指令的实现代码

    目标 使用vue2.0实现自定义弹窗指令,当标签有该指令时,点击标签可以弹出弹窗 实现 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <met

  • vue自定义tap指令及tap事件的实现

    1.Vue指令 Vue提供自定义实现指令的功能, 和组件类似,可以是全局指令和局部指令,详细可以参见vue官网自定义指令一节(https://cn.vuejs.org/v2/guide/custom-directive.html). 2.v-tap指令实现 我个人的理解,编写指令即是在vue指令对象提供的钩子函数中做相应的逻辑处理,tap指令是在bind钩子函数中做相应的处理, 首先,要明白的是tap是为了处理click事件在iphone上的存在300ms的延时,这样使得连续点击很不流畅,tap

  • Vue自定义v-has指令,做按钮权限判断的步骤

    应用场景 以后台管理系统为例,每个用户所拥有的按钮权限不一样.管理员配置权限之后,用户登录时,从接口拿到按钮权限列表,然后根据后台数据判断显示哪些按钮. 简单说一下,自定义指令 Vue.js官网关于自定义指令的讲解 cn.vuejs.org/v2/guide/cu- 基础概念 Vue除了核心功能默认内置的指令(v-model和v-show)还可以注册自定义指令. 在Vue2.0中,代码复用和抽象的主要形式是组件.但有的情况下,仍需要对普通DOM元素进行底层操作,这时候就会用到自定义指令. 譬如,

  • Vue自定义v-has指令实现按钮权限判断

    应用场景 以后台管理系统为例,每个用户所拥有的按钮权限不一样.管理员配置权限之后,用户登录时,从接口拿到按钮权限列表,然后根据后台数据判断显示哪些按钮. 简单说一下,自定义指令 Vue.js官网关于自定义指令的讲解 cn.vuejs.org/v2/guide/cu- 基础概念 Vue除了核心功能默认内置的指令(v-model和v-show)还可以注册自定义指令. 在Vue2.0中,代码复用和抽象的主要形式是组件.但有的情况下,仍需要对普通DOM元素进行底层操作,这时候就会用到自定义指令. 譬如,

  • Vue自定义复制指令 v-copy功能的实现

    使用自定义指令创建一个点击复制文本功能 1. 创建v-copy.js文件 import Vue from "vue"; // 注册一个全局自定义复制指令 `v-copy` Vue.directive("copy", { bind(el, { value }) { el.$value = value; el.handler = () => { el.style.position = 'relative'; if (!el.$value) { // 值为空的时候,

  • vue自定义封装按钮组件

    vue按钮组件的自定义封装代码,供大家参考,具体内容如下 封装按钮组件 button.vue <template> <button class="button ellipsis" :class="[size,type]"> <slot /> </button> </template> <script> export default { name: 'Button', props: { size:

  • Vue的土著指令和自定义指令实例详解

    1.土著指令 当我开始学习Vue的时候,看官网的时候看到了"指令"两个字.我愣住了,what?指令是啥啊?后来继续往下看,像这种什么"v-for""v-show""v-if"都叫做指令.等到后来Vue玩的差不多了,开始写项目的时候发现,常见的指令也就那么几个,比如"v-if""v-show""v-model""v-for""v-bind&

随机推荐