• 实现自动获取焦点(autofocus)
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
 // 当被绑定的元素插入到 DOM 中时……
 inserted: function (el) {
   // 聚焦元素
   el.focus()
 }
})
  • directives(局部组件自定义事件属性)
  • 注意focus处的字段名是自定义的名字,最好不重样,如果和原生事件名相同,会覆盖掉原生事件
directives: {
  focus: {
    // 指令的定义
    bind:function(el,binding,vnode,oldVnode){
    	console.log('bind:function',el,binding,vnode,oldVnode)
	},
    inserted:function (el,binding,vnode,oldVnode) {
    	console.log('inserted:function',el,binding,vnode,oldVnode)
      	el.focus()
    },
    update:function(el,binding,vnode,oldVnode) {
		console.log('update:function',el,binding,vnode,oldVnode)
	},
    componentUpdated:function(el,binding,vnode,oldVnode) {
		console.log('componentUpdated:function',el,binding,vnode,oldVnode)
	},
    unbind:function(el,binding,vnode,oldVnode) {
		console.log('unbind:function',el,binding,vnode,oldVnode)
	}
  }
}

关于自定义命令的参数说明

  • 关于directives的事件参数说明

除了 el参数 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。

bind:function(el, binding, vnode, oldValue) {} // 参数均为可选
inserted:function(el, binding, vnode, oldValue) {} // 参数均为可选
update:function(el, binding, vnode, oldValue) {} // 参数均为可选
componentUpdated:function(el, binding, vnode, oldValue) {} // 参数均为可选
unbind:function(el, binding, vnode, oldValue) {} // 参数均为可选
钩子函数说明:
bind:指令第一次绑定到元素时使用,这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用,仅保证父节点存在,但不一定已被插入文档中。
update:指令的值可能发生了改变,也可能没有.所在组件的 VNode 更新时调用
,但是发生在其子VNode调用之前。
componentUpdated:指令在所有的VNode及其所有子VNode的更新之后调用。
unbind:只调用一次,指令与元素解绑时调用

函数参数说明:
el:指令所绑定的DOM元素,可以直接操作元素。
binding:一个对象,包含以下property
- name:指令名,不包含'v-'前缀。
- value:指令的绑定值,即通过v-demo="参数",参数(计算后)传过来的计算结果。
- oldValue:指令绑定的前一个值,仅在update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
- expression:字符串形式的指令表达式,v-demo="1 + 1" ,这里参数值就是"1 + 1"- arg:传给指令的参数,可选。例如v-demo:foo,这里的参数值就是'foo'- modifiers:一个包含修饰符的对象,例如v-demo.a.b,参数的值为{a:true,b:true}
vnode:vue编译生成的虚拟节点。
oldVnode:上一个虚拟节点,仅在update和componentUpdated钩子函数中可用。

动态指令组件

比如v-demo:[argument]="value";这里的argument参数就是可以更改;
举例:
<template>
<div class="root" style="position:relative;">
	<p v-position:[param]="200">动态指令组件来实现不同位置的定位</p>
</div>
</template>
<script>
export default {
  data(){
	return {param:'left'}
  },
  directives:{
	position:{
	 bind: function (el, binding, vnode) {
	  el.style.position = 'absolute'
      el.style[binding.arg] = binding.value + 'px' // el.style.left = 200 + 'px'
     }
	}	
  }
}
</script>

动态指令(vue3)

加载图

在这里插入图片描述

目录结构:
loading:
-loading.gif
-loading.vue
-directive.js
assets/js:
-dom.js
对应文件内容:
// loading.vue 
<template>
  <div class="loading">
    <div class="loading-content">
      <img width="24" height="24" src="./loading.gif" />
      <p class="desc">{{title}}</p>
    </div>
  </div>
</template>

<script>
  export default {
    name: "Loading",
    data() {
      return {
        title: "正在载入..."
      };
    },
    methods: {
      setTitle(title) {
        this.title = title;
      }
    }
  };
</script>
<style lang="scss" scoped>
  .loading {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate3d(-50%, -50%, 0);
    .loading-content {
      text-align: center;
      .desc {
        line-height: 20px;
        font-size: $font-size-small;
        color: $color-text-l;
      }
    }
  }
</style>

// directive.js
import { addClass, removeClass } from '@/assets/js/dom'

import Loading from './loading'
import { createApp } from 'vue'

const relativeCls = 'g-relative'
const loadingDirective = {
  mounted(el, binding) {
    // 创建Loading组件实例
    const app = createApp(Loading)
    // 将loading组件挂载给空div,后面就可以拿到组件dom
    const instance = app.mount(document.createElement('div'))
    el.instance = instance
    // 动态加载描述内容
    const title = binding.arg
    if (typeof title !== 'undefined') {
      instance.setTitle(title)
    }
    // v-loading="binding.value"
    if (binding.value) {
      append(el)
    }
  },
  updated(el, binding) {
    // 更新后的描述内容 binding.arg
    if (typeof binding.arg !== 'undefined') {
      el.instance.setTitle(binding.arg)
    }
    // 更新后如果入参前后不一致,就判断进行页面loading结构的添加,展示
    if (binding.value !== binding.oldValue) {
      binding.value ? append(el) : remove(el)
    }
  }
}

export default loadingDirective

function append(el) {
  // 获取到使用该指令的指定元素样式
  const styles = getComputedStyle(el)
  // 如果绑定的元素没有定位,则主动添加
  if (!['relative', 'absolute', 'fixed'].includes(styles.position)) {
    addClass(el, relativeCls)
  }
  el.appendChild(el.instance.$el)
}

function remove(el) {
  // 等待loading加载完毕后删除掉对应的定位类名
  removeClass(el, relativeCls)
  el.removeChild(el.instance.$el)
}

// dom.js
function addClass(el, className) {
  if (!el.classList.contains(className)) {
    el.classList.add(className);
  }
}

function removeClass(el, className) {
  if (el.classList.contains(className)) {
    el.classList.remove(className);
  }
}

export {
  addClass, removeClass
}
接下来最重要的就是注册使用:
1. 注册
// main.js
import App from './App.vue'
import LoadingDirective from '@/directives/loading/directive'
// 注册
const app = createApp(App)
app.use(router).directive('loading', LoadingDirective)
2.使用
// 随意一个需要使用loading的vue文件
<div v-loading['加载文本']="Boolean值">...</div>
Logo

前往低代码交流专区

更多推荐