vue 自定义指令directive

2,265 阅读2分钟

全局指令

全局指令 所有的组件 实例都可以使用

  • 指令有几部分组成v-model.a.b.c='abc',指令名、修饰符、指令绑定属性
  • el代表当前指令元素
  • bindings绑定属性
  • vnode虚拟节点 context上下文,当前指令所在的上下文(一般为this
  • 指令钩子函数,bind inserted update unbind
    bind初始化的时候绑定(dom节点还未插到页面上),此方法 默认只在绑定的时候 才会执行 和 更新的时候也会重新执行(只有依赖的数据发生变化才会重新执行)
    update数据更新的时候绑定(dom节点还未插到页面上),此方法 默认只在绑定的时候 才会执行 和 更新的时候也会重新执行(只有依赖的数据发生变化才会重新执行)
    inserteddom节点插到页面后执行,一般都会使用此钩子
    unbind指令销毁的时候 会触发此函数
例子:让输入框自动获取焦点
//html
<div id="app">
    <input type="text" v-focus.color="a"/>
</div>
<!--写法1(不建议)-->
Vue.directive('focus',function (el,bindings,vnode){
    //此函数相当于directive中的bind函数
})
<!--写法2(建议)-->
Vue.directive('focus',{
    inserted(el,bindings,vnode){
        //指令元素插入到页面时执行
        //bindings.modifiers是修饰符,要么没有,有就为true
        if(bindings.modifiers.color){
            el.style.background = bindings.value
        }
        el.focus();
    }
})

new Vue({
    el:'#app',
    data:{
        a:'red'
    }
})

bindings

局部指令 directives 可注册多个

例子

局部注册一个指令v-click-outside,完成input获取焦点时,div.content显示;失去焦点时,div.content消失
⚠注意:点击div.content里面的按钮时,input已经失去焦点,此时div.content不能消失,否则为bug

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        input{
            border:1px solid red;
        }
        .content{width: 100px;height: 100px;background: yellowgreen;}

    </style>
</head>
<body>
    <div id="app">
        <!-- 日历 弹层 -->
        <div v-click-outside>
            <input type="text"/>
            <div class="content" v-if="isShow">content
                <button>点击</button>
            </div>
        </div>
    </div>
</body>
</html>
<script src="node_modules/vue/dist/vue.js"></script>
<script>

    let vm = new Vue({
        el:'#app',
        directives:{//可以声明多个所以是复数形式
            clickOutside:{//可以实现 点击时判断是否存在当前的dom中
                bind(el,bindings,vnode){
                    el.fn = (e)=>{
                        //.contains() 判断一个元素内是否包含另一个元素
                        console.log(e.target)
                        if(el.contains(e.target)){
                            alert('点击的属于el里面')
                            console.log(vnode.context)
                            vnode.context['focus']()
                        }else{
                            vnode.context['blur']()
                        }
                    }
                    document.addEventListener('click',el.fn)
                },
                unbind(el){
                    //事件绑定 必须要解绑
                    document.addEventListener('click',el.fn)
                }
            }

        },
        data:{
            isShow:false
        },
        methods:{
            focus(){
                this.isShow = true;
            },
            blur(){
                this.isShow = false
            }
        }
    })
</script>