前端基础之《Vue(11)—自定义指令》

一、自定义指令

1、自己封装指令

什么是指令?指令本质上就是DOM功能的一种抽象封装。

如果有一些DOM功能经常用,但是Vue没有提供相关指令,建议自己封装。

2、自定义全局指令

使用Vue.directive('指令名', function() {})定义全局指令。

3、自定义局部指令

使用directives: {}定义局部指令,只能在当前组件中使用。

(1)使用function写法

javascript 复制代码
directives: {
    // function写法
    'color': function(el, binding, vnode) {
        console.log('---el', el) // 指令所对应的DOM节点
        console.log('---binding', binding) // 绑定的值/表达式
        console.log('---vnode', vnode) // 当前的虚拟DOM
        el.style.color = binding.value
    }
}

接收3个参数:

el:指令所对应的DOM节点

binding:绑定的值/表达式

vnode:当前的虚拟DOM

(2)使用对象写法

javascript 复制代码
directives: {
    // function写法
    'color': function(el, binding, vnode) {
        console.log('---el', el) // 指令所对应的DOM节点
        console.log('---binding', binding) // 绑定的值/表达式
        console.log('---vnode', vnode) // 当前的虚拟DOM
        el.style.color = binding.value
    },
    // 对象写法
    'color2': {
        bind(el, binding) { // 绑定cc变量的时候
            el.style.color = binding.value
        },
        update(el, binding) { // 修改cc变量的时候
            el.style.color = binding.value
        }
    }
}

还有其它的钩子。

注:function写法,等价于bind + update这两个。

二、例子代码

自己封装一个指令v-form,类似于v-model指令实现双向绑定。

必须要用虚拟DOM的上下文实现。

html 复制代码
<html>
<head>
    <title>自定义指令</title>
    <style>
        
    </style>
</head>
<body>
    <div id="app">
        <h1 v-color='"red"'>测试</h1>
        <h1 v-color='"blue"'>测试</h1>
        <h1 v-color2="cc">测试</h1>
        <input type="text" v-form.lazy="name" />
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>

    <script>
        Vue.directive ('form', {
            bind(el, binding, vnode) {
                console.log('---el', el)
                console.log('---binding', binding)
                console.log('---vnode', vnode)

                // 解构赋值
                const { lazy } = binding.modifiers

                // v-bind:value
                // 指令在绑值的时候,改上下文中的值
                el.value = vnode.context[binding.expression]
                // v-on:input
                // 实现双向绑定
                el.addEventListener(lazy?'blur':'input', function(ev){
                    console.log('---事件', ev.target.value)
                    vnode.context[binding.expression] = ev.target.value
                })
            },
            update(el, binding, vnode) {
                // 实现双向绑定
                el.value = vnode.context[binding.expression]
            }
        })

        const app = new Vue({
            data() {
                return {
                    cc: "green",
                    name: '张三'
                }
            },
            directives: {
                // function写法
                'color': function(el, binding, vnode) {
                    //console.log('---el', el) // 指令所对应的DOM节点
                    //console.log('---binding', binding) // 绑定的值/表达式
                    //console.log('---vnode', vnode) // 当前的虚拟DOM
                    el.style.color = binding.value
                },
                // 对象写法
                'color2': {
                    bind(el, binding) { // 绑定cc变量的时候
                        el.style.color = binding.value
                    },
                    update(el, binding) { // 修改cc变量的时候
                        el.style.color = binding.value
                    }
                }
            }
        })
        app.$mount('#app')

    </script>

</body>
</html>
相关推荐
Misnice2 分钟前
Webpack、Vite、Rsbuild区别
前端·webpack·node.js
青茶3603 分钟前
php怎么实现订单接口状态轮询(二)
前端·php·接口
大橙子额1 小时前
【解决报错】Cannot assign to read only property ‘exports‘ of object ‘#<Object>‘
前端·javascript·vue.js
爱喝白开水a2 小时前
前端AI自动化测试:brower-use调研让大模型帮你做网页交互与测试
前端·人工智能·大模型·prompt·交互·agent·rag
董世昌412 小时前
深度解析ES6 Set与Map:相同点、核心差异及实战选型
前端·javascript·es6
吃杠碰小鸡3 小时前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone3 小时前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_09014 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农4 小时前
Vue 2.3
前端·javascript·vue.js
夜郎king4 小时前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落