记录一下第一次实现Vue自定义指令

76 阅读1分钟

前言

毕业一年多以来居然没有去了解过Vue自定义指令,工作的时候都是使用官方的一些常用指令。今天逛文章的时候恰巧看到了,正好抽时间学习整理一下。简单的写了一个小demo,希望大佬们多多指教。

一、 关于Vue自定义指令

参数方面就不列举了cn.vuejs.org/guide/reusa… 官网写得很详细。需要注意的是 bind 函数只调用 1 次:当指令第一次绑定到元素时调用,当 DOM 更新时bind 函数不会被触发。 update 函数会在每次 DOM 更新时被调用。

directives: {
    myloading: {
        // 只调用一次
        bind (el, target) {},
        // 每次 DOM 更新调用
        update (el, target) {}
    },
},

二、 局部loading Demo

  1. 写一个简单的Loading组件,大概长这样。我这个是为了快,props这些都没写。

loading-pic.png

<template>
    <div class="base-loading">
        <div class="spinner">
            <div class="circular"></div>
            <div class="text">加载中...</div>
        </div>
    </div>
</template>
<script>
export default {};
</script>
<style lang="less" scoped>
.base-loading {
    position: absolute;
    z-index: 2000;
    background-color: hsla(0, 0%, 100%, 0.9);
    margin: 0;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    display: flex;
    justify-content: center;
    width: 100%;
    transition: opacity 0.3s;
    .spinner {
        top: 50%;
        position: absolute;
        .text{
            margin-top: 12px;
            font-size: 12px;
        }
	.circular {
            height: 42px;
            width: 42px;
            border-left: 3px solid #49e;
            border-radius: 50%;
            animation: loading-rotate 2s ease-out infinite;
            }
    }
    @keyframes loading-roate {
        100% {
            transform: rotate(1turn);
	}
    }
}
</style>

  1. 创建Loading组件实例对象,为了获取组件的VNode。
import BaseLoading from "@/components/base-loading";
import Vue from "vue";

const Loading = Vue.extend(BaseLoading);
const loading = new Loading({
    el: document.createElement("div"),
    data: {}
});
  1. 编写指令
directives: {
    myloading: {
        bind (el, target) {
            if (target.value) {
                el.style.position = "relative";
                el.appendChild(loading.$el);
            }
        },
        update (el, target) {
            // 绑定值为true
            if (target.value) {
                el.style.position = "relative";
                el.appendChild(loading.$el);
            }else{ // false 移除dom
                el.removeChild(loading.$el);
            }
        }
    },
}
  1. 激动的测试环节
<div class="questionnaire-wrap" v-myloading="isloading"></div>
<div class="show-loading-btn" @click="checkDomLoading">点击切换loading</div>

data() {
    return {
        isloading: false;
    }
},
method : {
    checkDomLoading(){
        this.isloading = !this.isloading
    }
}

三、 拓展

自定义事件指令大同小异,通过向el添加对应事件即可。

<div class="questionnaire-wrap" v-myclick="clickHandle"></div>

directives: {
    myclick: {
        bind (el, target) {
            // 这时候target.value需为Function,需要特殊处理
            el.addEventListener("click", target.value);
        }
    }
},

method : {
    clickHandle(){
        console.log('事件被触发!')
    }
}

四、 结语

写得很粗糙,随意看看。不喜勿喷,8年祖安青铜选手。

指令使用时记得加v-。写demo时在获取组件$el时候卡了半天,翻了好久案例才找到。