Vue---自定义指令directive的全局注册和局部注册(含vue3)
实现自动获取焦点(autofocus)// 注册一个全局自定义指令 `v-focus`Vue.directive('focus', {// 当被绑定的元素插入到 DOM 中时……inserted: function (el) {// 聚焦元素el.focus()}})directives(局部组件自定义事件属性)注意focus处的字段名要是事件名,而非自定义的名字directives: {focu
·
- 实现自动获取焦点(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>
更多推荐
已为社区贡献9条内容
所有评论(0)