Vue 教程第八篇—— 自定义指令

本文详细介绍了Vue中自定义指令的使用方法,包括全局指令与局部指令的区别,以及如何通过钩子函数实现复杂的操作。同时提供了自定义日期控件的具体案例。

自定义指令

在某些情况下,Vue 提供给我们的指令是非常不够的,比如有一个输入框需要在点击的时候能弹出日期控件,这个功能 Vue 并不支持,但 Vue 支持我们自定义指令。

自定义指令和定义组件的方式很类式,也是有全局指令和局部指令之分

全局指令

    <div id="app">
        <!--在这里使用了一个自定义的指令 v-global-->
        <input type="text" value="" v-global />
    </div>
    // 注册一个全局自定义指令 v-global,指令名称不用加前缀 v-
    // 当元素使用了 v-global 这个指令时会触发对应的 function
    // 参数 element:使用指令的元素
    Vue.directive('global',  function(element){
        //默认触发钩子函数的 inserted
        element.value = "世界和平";
        element.focus();
    })

    var vm = new Vue({
        el: '#app'
    })

局部指令

    <div id="app">
        <!--在这里使用了一个自定义的指令 v-private-->
        <input type="text" value="" v-private />
    </div>
    var vm = new Vue({
        el: '#app',
        directives: {
            //注册一个局布指令 private,指令名称不用加前缀 v-
            // 当元素使用了 v-private 这个指令时会触发对应的 function
            // 参数 element:使用指令的元素
            private: function(element){
                element.style.background = '#ccc';
                element.value = "世界和平";
            }
        }
    })

效果预览

钩子函数

钩子函数可以理解成是指令的生命周期

    <div id="app">
        <!--在这里使用了一个自定义的指令 v-global-->
        <input type="text" v-model="text" v-demo="{color:'red'}">
    </div>
    Vue.directive('demo', {
        //被绑定元素插入父节点时调用
        //默认触发此方法 Vue.directive('demo',  function(element){})
        //后于 bind 触发 
        //参数 element: 使用指令的元素
        //参数 binding: 使用指令的属性对象
        //参数 vnode: 整个 Vue 实例
        inserted: function(element, binding, vnode){
            console.log('inserted');
        },
        //只调用一次,指令第一次绑定到元素时调用,
        //用这个钩子函数可以定义一个在绑定时执行一次的初始化动作
        //先于 inserted 触发
        bind: function(element, binding, vnode){
            console.log('bind');
            element.style.color = binding.value.color
        },
        //被绑定元素所在的模板更新时调用,而不论绑定值是否变化
        update: function(element, binding, vnode){
            console.log('update');
        },
        //被绑定元素所在模板完成一次更新周期时调用。
        componentUpdated: function(element, binding, vnode){
            console.log('componentUpdated');
        }
    })

    var vm = new Vue({
        el: '#app',
        data:{
            text: '钩子函数'
        }
    })

效果预览

案例:自定义日期控件

这里用 boostrap 的 datepicker 插件实现

    <div id="app">
        <!--直接在 jQuery 环境下使用 datepicker 插件-->
        <input type="text" id="datepicker" data-date-format="yyyy-mm-dd"/>
        <!--使用 Vue 自定义指令 v-datepicker-->
        <input type="text" v-datepicker data-date-format="yyyy-mm-dd"/>
        <input type="button" value="保存" @click="save">
        <span>{{dataform.birthday}}</span>
    </div>
    //在没有使用 Vue 前,datepicker 插件在 jQuery 的环境下是这样使用
    $('#datepicker').datepicker();

    //使用 Vue 自定义指令 v-datepicker
    Vue.directive('datepicker', function(element, binding, vnode){
        // data = dataform.birthday
        $(element).datepicker({
            language: 'zh-CN',
            pickTime: false,
            todayBtn: true,
            autoclose: true
        }).on('changeDate', function(){
            //由于不是手动在 input 输入值,所以双向绑定 v-model 无效
            //所以需要手动改变实例的数据模型
            var data = $(element).data('model');
            if(data){
                // datas = ['dataform', 'birthday']
                var datas = data.split('.');
                //context = vm
                var context = vnode.context;
                //循环属性自动添加
                datas.map((ele, idx) => {
                    //最后一个属性就直接赋值
                    if(idx == datas.length - 1){
                        context[ele] = element.value
                    } else {
                        //动态添加属性
                        context = context[ele]
                    }
                })
            }
        })
    })

    var vm = new Vue({
        el: '#app',
        data: {
            dataform: {}
        },
        methods: {
            save: function(){
                //使用 $set 更新 dataform
                //更多 $set 的使用在下面继续介绍
                this.$set(this.dataform)
            }
        }
    })

$set 介绍

当实例对象 data 先设置好了结构,比如:data: {dataform: {}},在后期想添加一个属性 username 时,这个 username 不会自动绑定到视图当中,所以调用 $set(原对象,新属性名,属性值) 进行绑定到视图当中

    <div id="app">
        <input type="button" value="set" @click="set">
        <span>{{dataform.username}}</span>
    </div>
    var vm = new Vue({
        el: '#app',
        data: {
            dataform: {}
        },
        methods: {
            set: function(){
                // 直接赋值不会显示在视图上
                // this.dataform.username = '123'
                //改用 $set 更新可以在视图上显示
                this.$set(this.dataform, 'username', '123')
            }
        }
    })

效果预览

### Vue.js 中自定义指令的详细用法 #### 一、什么是自定义指令Vue 提供了一些内置指令,比如 `v-text` 和 `v-if` 等。然而,在某些场景下这些内置指令可能无法满足需求,因此 Vue 允许开发者创建自己的指令来扩展功能[^2]。 #### 二、注册全局与局部自定义指令 自定义指令可以通过两种方式注册:全局和局部。 - **全局注册**:通过 `app.directive(name, definition)` 方法实现,适用于整个应用范围内的指令- **局部注册**:在组件选项中的 `directives` 属性内声明,仅限于该组件内部使用。 #### 三、钩子函数及其生命周期 当绑定到 DOM 节点上时,自定义指令会经历一系列钩子函数调用过程: 1. **bind**: 只调用一次,指令第一次绑定到元素时调用。 2. **inserted**: 当被绑定的元素插入父节点时调用。 3. **update**: 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。 4. **componentUpdated**: 指令所在组件的 VNode 及其子 VNode 都更新后调用。 5. **unbind**: 只调用一次,指令与元素解绑时调用。 以下是各阶段的具体说明以及示例代码: ```javascript // 定义一个简单的自定义指令 const app = Vue.createApp({}); app.directive('focus', { bind(el, binding, vnode) { console.log('Bind:', el); // 绑定时触发 }, inserted(el) { el.focus(); // 插入DOM树之后自动获取焦点 }, update(el, binding) { console.log('Update:', binding.value); } }); ``` 上述例子展示了如何利用 `bind`, `inserted` 来设置默认行为,并监控数据变化[^1]。 #### 四、参数传递给自定义指令 除了基本的功能外,还可以向自定义指令传参,增强灵活性。例如下面的例子演示了一个带有修饰符 `.lazy` 的输入框验证逻辑: ```html <input v-my-validator.lazy="validationRules"> ``` 对应的 JavaScript 实现如下所示: ```javascript app.directive('myValidator', (el, binding) => { const modifiers = binding.modifiers; if(modifiers && modifiers['lazy']){ // 延迟执行特定操作... } let rules = binding.value || []; function validate(inputValue){ return rules.every(rule=>rule.test(inputValue)); }; el.addEventListener('input',(e)=>{ e.target.setCustomValidity(validate(e.target.value)? '':'Invalid Input'); }); }); ``` 此部分解释了如何接收来自模板层面上的数据并通过回调处理业务逻辑[^3]。 #### 五、实际案例分析——数值放大器 为了更直观理解以上理论知识点的应用价值,我们来看一段完整的实例程序片段: ```html <template> <div id="example"> <p>原始数字:<strong>{{number}}</strong></p> <p><span v-multiply="multiplier">{{number}}</span>x{{multiplier}}=<span ref="result"></span></p> </div> </template> <script> export default{ directives:{ multiply:{ mounted:function(el,binding,vnode){ var resultElement=vnode.refs.result; resultElement.textContent=(binding.value*parseFloat(vnode.context.number)).toFixed(2); } } }, data(){ return{ number:7,multiplier:8}; } } </script> ``` 这里实现了动态计算乘积并显示结果的效果。 --- ### 总结 综上所述,Vue 自定义指令提供了一种强大而灵活的方式来操控 DOM 或者封装复杂的交互模式。无论是简单属性修改还是复杂事件监听都可以借助它完成高效开发工作流转换[^2].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值