首页 > 技术文章 > Vue3中的自定义指令

feiying3995 2021-11-05 18:20 原文

有了前面组件、mixin的基础之后,再来了解今天小编要说的内容,就相对容易一些,今天小编和大家一起学习Vue3中的自定义指令,我们先来看看什么是Vue中的指令。

除了核心功能默认内置的指令 (例如 v-model 和 v-show),Vue 也允许注册自定义指令。注意,在 Vue 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令

这是一段来自Vue3官网的一段话,用来解释什么是自定义指令,自定义指令产生的原因和实际应用
实际开发中,我们可能有这样的需求:页面中加载一个文本框,为了优化用户体验,需要在页面加载完成之后,自动获取焦点,在没有自定义指令的时候,我们会通过原生DOM这样处理这个问题

const app = Vue.createApp({
    mounted(){
        this.$refs.input.focus()
    },
    template:`<div>
            <input ref="input" />
        </div>`
})

const vm = app.mount("#root")

下面我们看看在全局注册一个自定义指令是一种什么样的体验

const app = Vue.createApp({
    template:`<div>
            <input v-focus />
        </div>`
})

app.directive('focus',{
    mounted(el){
        el.focus()
    }
})
const vm = app.mount("#root")

同样,我们也可以注册一个局部的自定义指令

const directives = {
    focus: {
        mounted(el) {
            el.focus()
        }
    }
}
const app = Vue.createApp({
    directives:directives,
    template: `<div>
            <input v-focus />
        </div>`
})

const vm = app.mount("#root")

这样,我们最开始的需求是满足了,但是有的时候,我们也想像Vue其他的指令一样,在指令后面添加指定的指,然后根据这个值相应对应的样式或者其他属性。比如我们定义一个v-pos属性,然后元素的距离上边距的距离刚好是这个数字,这个时候,我们可以写成这样

const directives = {
    focus: {
        mounted(el) {
            el.focus()
        }
    }
}
const app = Vue.createApp({
    data(){
    return {
            top:400
        }
    },
    template: `<div v-pos="top" class="header">
            <input />
            <button @click="top += 20">修改高度</button>
        </div>`
})

app.directive('pos',{
    mounted(el, binding){
        el.style.top = binding.value + 'px'
    },
    updated(el, binding){
        el.style.top = binding.value + 'px'
    }
})

const vm = app.mount("#root")

解决了一个问题,但是我们并不满足,我们希望根据自定义指令后面的属性不同,调整元素的样式,也就是希望在自定义指令后跟的是left,我们希望就是距离左边的距离,同样,后面跟的是right,就是距离右侧的距离,我们就可以这样

const directives = {
    focus: {
        mounted(el) {
            el.focus()
        }
    }
}
const app = Vue.createApp({
    data(){
        return {
            distance:400
        }
    },
    template: `<div v-pos:left="distance" class="header">
            <input />
        </div>`
})

app.directive('pos',(el, binding) => {
    console.log(binding, 'binding') // {arg: "abc",value:400}
    el.style[binding.arg] = binding.value + 'px'
})

const vm = app.mount("#root")

大家还可以扫描二维码,关注我的微信公众号,蜗牛全栈。

 

推荐阅读