vue指令
基本知识
-
类型:Directive
-
指令钩子
const myDirective = {
// 在绑定元素的 attribute 前
// 或事件监听器应用前调用
created(el, binding, vnode, prevVnode) {
// 下面会介绍各个参数的细节
},
// 在元素被插入到 DOM 前调用
beforeMount(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件
// 及他自己的所有子节点都挂载完成后调用
mounted(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件更新前调用
beforeUpdate(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件
// 及他自己的所有子节点都更新后调用
updated(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载前调用
beforeUnmount(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载后调用
unmounted(el, binding, vnode, prevVnode) {}
}
- 参数意义
- el:绑定的元素的DOM,可以DOM修改
- binding:
- value:指令传递过来的值
- oldValue:旧的值
- arg:指令 传递过来的参数
- modifiers一个包含修饰符的对象 (如果有的话)。例如在
v-my-directive.foo.bar
中,修饰符对象是{ foo: true, bar: true }
。
- instance:使用该指令的组件实例
vnode
:代表绑定元素的底层 VNode。prevVnode
:代表之前的渲染中指令所绑定元素的 VNode。仅在beforeUpdate
和updated
钩子中可用
案例 实现指令loading
定义loading模板
<template>
<div class="loading">
<img src="../../assets/gif/20210622113522288.gif" alt="" />
</div>
</template>
<script setup lang="ts"></script>
<style scoped lang="less">
.loading {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
display: flex;
justify-content: center;
align-items: center;
img {
width: 10%;
object-fit: cover;
}
}
</style>
指令编写
需求分析:loading指令,需要是在指定父系组件上使用,可以在这个组件内根据传入loading的真假,来动态显示loading。
- Dom挂载
import Vue, { ComponentPublicInstance, Directive, createApp } from "vue";
import Loading from "../components/loading/index.vue";
let loadingDom: ComponentPublicInstance;
let elPos: string;
//组件初始化
const init = (el: HTMLElement) => {
const app = createApp(Loading);
loadingDom = app.mount(document.createElement("div"));
elPos = window.getComputedStyle(el).position;
};
//移除
const addLoading = (el: HTMLElement) => {
removeLoading(el);
if (elPos === "static") {
el.style.position = "relative";
}
el.appendChild(loadingDom.$el);
};
//添加
const removeLoading = (el: HTMLElement) => {
el.style.position = elPos || "static";
if (el.contains(loadingDom.$el)) {
el.removeChild(loadingDom.$el);
}
};
- 指令内容编写
export const loadingDirective: Directive = {
mounted(el: HTMLElement, binding) {
init(el);
if (binding.value === true) {
addLoading(el);
} else {
removeLoading(el);
}
},
updated(el: HTMLElement, binding) {
if (binding.value === true) {
addLoading(el);
} else {
removeLoading(el);
}
},
};