vue3基础入门-p08-自定义指令

自定义指令

除了核心功能默认内置的指令 (例如 v-model 和 v-show),Vue 也允许注册自定义指令

有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。

比如:获取文本框的焦点

自定义指令

  • 定义一个全局的指令
const app = Vue.createApp({})
// 注册一个全局自定义指令 `v-focus`
// 参数1: 指令名
// 参数2: 指令的配置项
app.directive('focus', {
    // 当被绑定的元素挂载到 DOM 中时……
    mounted(el) {
        // 聚焦元素
        el.focus()
    }
})
  • 定义一个局部的指令

如果想注册局部指令,组件中也接受一个 directives 的选项:

directives: {
    focus: {
        // 指令的定义
        mounted(el)
        {
            el.focus()
        }
    }
}
  • 使用自定义指令
<input v-focus>

实现一个v-focus指令


<body>
<div id="app">
    <input/>
    <!--使用自定义指令-->
    <input v-focus/>
    <input/>

</div>

<script src="./node_modules/vue/dist/vue.global.js"></script>

<script>

    const app = Vue.createApp({})

    // 注册一个全局自定义指令 `v-focus`
    // 参数1: 指令名
    // 参数2: 指令的配置项
    app.directive('focus', {
        // 当被绑定的元素挂载到 DOM 中时……
        mounted(el) {
            // 聚焦元素
            el.focus()
        }
    })
    const vm = app.mount('#app')
    window.vm = vm
</script>
</body>

指令的钩子函数

一个指令定义对象可以提供如下几个钩子函数 (均为可选):

  • created:在绑定元素的 attribute 或事件监听器被应用之前调用。在指令需要附加在普通的 v-on 事件监听器调用前的事件监听器中时,这很有用。

  • beforeMount:当指令第一次绑定到元素并且在挂载父组件之前调用。

  • mounted:(重点) 当被绑定的元素挂载到 DOM 中后调用。

  • beforeUpdate:在更新包含组件的 VNode 之前调用。

  • updated:(重点) 在包含组件的 VNode 及其子组件的 VNode 更新后调用。

  • beforeUnmount:在卸载绑定元素的父组件之前调用

  • unmounted:当指令与元素解除绑定且父组件已卸载时,只调用一次。

钩子函数的参数

vue中一个完整的指令,格式为:v-指令名:指令的参数.指令的修饰符.指令的修饰符 = '指令的值',例如: v-on:click.stop.prevent = "clickFn"
所有的钩子函数的参数都是一个样,主要有两个参数elbinding

  • 参数1: el el表示指令所在的DOM元素
  • 参数2: binding : 是一个对象,有很多属性,包含了指令中所有的信息
    • arg: 传给指令的参数,可选 :参数。 例如v-on:click.stop.prevent = "clickFn"中,arg参数为 click
    • value: 指令的绑定值,例如v-on:click.stop.prevent = "clickFn" 中,value值为 clickFn
    • modifiers: 指令的修饰符,可以有多个。例如 v-on:click.stop.prevent = "clickFn"中,modifiers为 {stop: true, prevent: true}

实现一个v-on指令


<body>
<div id="app">
    <a href="http://www.baidu.com" v-on:click.stop.prevent="clickFn">点我v-on</a> |
    <!--使用自定义指令-->
    <a href="http://www.baidu.com" v-myon:click.stop.prevent="clickFn">点我-v-myon</a>
</div>

<script src="./node_modules/vue/dist/vue.global.js"></script>

<script>

    const app = Vue.createApp({
        methods: {
            clickFn() {
                console.log("触发了点击事件...")
            }
        }
    })

    app.directive('myon', {
        mounted(el, binding) {
            console.log("el:", el)
            console.log("binding:", binding)
            console.log("arg:", binding.arg)
            console.log("value:", binding.value)
            console.log("modifiers:", binding.modifiers)
            // 给el注册事件, 注册什么事件 binding.arg
            el.addEventListener(binding.arg, function (e) {
                // 保证传进来的clickFn在每次触发的时候都应该执行
                binding.value()

                if (binding.modifiers.prevent) {
                    e.preventDefault()
                }
                if (binding.modifiers.stop) {
                    e.stopPropagation()
                }
            })

        }
    })
    const vm = app.mount('#app')
    window.vm = vm
</script>
</body>

自定义点击事件指令

实现一个v-text指令

<span v-mytext="msg"></span>

自定义指令:

app.directive('mytext', {
    mounted(el, binding) {
        el.innerText = binding.value
    }
})

实现一个v-color指令


<div v-color:bg="bgColor"> {{ bgColor }}</div>
<div v-color:font="fontSize">{{ fontSize }}</div>

自定义指令:

const app = Vue.createApp({
    data() {
        return {
            fontSize: '40px',
            bgColor: 'red'
        }
    }
})

app.directive('color', {
    mounted(el, binding) {
        if (binding.arg === 'font') {
            el.style.fontSize = binding.value
        }
        if (binding.arg === 'bg') {
            el.style.backgroundColor = binding.value
        }
    }
})

实现一个v-bind指令

<h1 v-mybind:title="msg">哈哈哈</h1>

自定义指令

app.directive('mybind', {
    mounted(el, binding) {
        el.setAttribute(binding.arg, binding.value)
    }
})

指令的简写

在很多时候,你可能想在 mountedupdated 时触发相同行为,而不关心其它的钩子。比如这样写:

app.directive('color', (el, binding) => {
    if (binding.arg === 'font') {
        el.style.fontSize = binding.value
    }
    if (binding.arg === 'bg') {
        el.style.backgroundColor = binding.value
    }
})

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。
My Show My Code