zoukankan      html  css  js  c++  java
  • VUE学习笔记--指令的注册

    自定义指令的注册分为全局注册和局部注册。
     语法:Vue.directive(id,definition)。id 是指令的唯一标识,definition 定义对象则是指令的相关属性及钩子函数。
    全局自定义指令,格式如下
    Vue.directive('focus', {    // 注册一个全局自定义指令 v-focus  
        //定义对象
     })
    也可以注册局部指令,格式如下:
    
    var vm = new Vue({
      el: '#app',
      directives:{
        focus:{
          //定义对象
        }
      }
    })
    指令的定义对象
    
    definition定义对象,对指令赋予具体的功能。可以提供如下几个钩子函数 (均为可选):
    bind:只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性的初始 化设置。 
    inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 ocument 中)。
    update:被绑定元素所在的模板跟新时调用,而不论绑定值是否变化。通过比较更 新前后绑定的值,可以忽略不必要的模板更新 。
    componentUpdated:被绑定元素所在模板完成一次更新周期时调用。
    unbind:只调用一次,指令与元素解绑时调用。 
    根据需求在不同的钩子函数内完成逻辑代码。
    (全局/局部) 自定义 v-focus 指令
    
    <!DOCTYPE html>
    <html xmlns:v-on="http://www.w3.org/1999/xhtml" xmlns:v-bind="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
        <meta charset="utf-8"/>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <p>页面载入时,input 元素自动获取焦点:</p>
        <input v-focus>
    </div>
    <script>
        // 注册一个全局自定义指令 v-focus
        /* Vue.directive('focus', {
             // 当绑定元素插入到 DOM 中。
             inserted: function (el) {
                 // 聚焦元素
                 el.focus()
             }
         })*/
        // 创建根实例
        var vm=new Vue({
            el: '#app',
            directives: {
                // 注册一个局部的自定义指令 v-focus
                focus: {
                    // 指令的定义
                    inserted: function (el) {
                        // 聚焦元素
                        el.focus()
                    }
                }
            }
        })
    </script>
    </body>
    </html>
    指令实例属性
    
    在指令的钩子函数内,可以通过 this 来调用指令实例。下面详细说明指令的实例属性。
    el:指令所绑定的元素,可以用来直接操作 DOM。 
    binding:一个对象,包含以下 property
    name:指令名,不包括 v- 前缀。 
    value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。 
    oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中 可用。无论值是否改变都可用。 
    expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达 式为 "1 + 1"。
    arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
    modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符 对象为 { foo: true, bar: true }。
    vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
     oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。 
    <!DOCTYPE html>
    <html xmlns:v-on="http://www.w3.org/1999/xhtml" xmlns:v-bind="http://www.w3.org/1999/xhtml"
          xmlns:v-demo="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
        <meta charset="utf-8"/>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app" v-demo:msg.a.b="message"></div>
    
    <script>
        Vue.directive('demo', {
            bind: function (el, binding, vnode) {
                var s = JSON.stringify
                el.innerHTML =
                    'name: '       + s(binding.name) + '<br>' +
                    'value: '      + s(binding.value) + '<br>' +
                    'expression: ' + s(binding.expression) + '<br>' +
                    'argument: '   + s(binding.arg) + '<br>' +
                    'modifiers: '  + s(binding.modifiers) + '<br>' +
                    'vnode keys: ' + Object.keys(vnode).join(', ')
            }
        })
        new Vue({
            el: '#app',
            data: {
                message: 'hello!'
            }
        })
    </script>
    </body>
    </html>
    <!DOCTYPE html>
    <html>
    <head>
        <title></title>
        <meta charset="utf-8"/>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <!--自定义指令v-clickoutside绑定handleHide函数-->
        <div class="main" v-clickoutside="handleHide">
            <button @click="show = !show">点击显示下拉菜单</button>
            <div class="dropdown" v-show="show">
                <div class="item"><a href="#">选项 1</a></div>
                <div class="item"><a href="#">选项 2</a></div>
                <div class="item"><a href="#">选项 3</a></div>
            </div>
        </div>
    </div>
    <script>
        /*自定义指令v-clickoutside*/
        Vue.directive('clickoutside', {
            /*在document上绑定click事件,所以在bing钩子函数内声明了一个函数
            documentHandler,并将它作为句柄绑定在document的click事件上。
            documentHandler函数做了两个判断。
            * */
            bind(el, binding) {
                function documentHandler(e) {
                    /*第一个是判断点击的区域是否是指令所在的元素内部,如果是,
                    就跳转函数,不往下继续执行。
                    * contains方法是用来判断元素A是否包含了元素B,包含返回true。
                    * */
                    if (el.contains(e.target)) {
                        return false
                    }
                    /*第二个判断的是当前的指令v-clickoutside有没有表达式,在该自定义
                    指令中,表达式应该是一个函数,在过滤了内部元素后,点击外面任何区
                    域应该执行用户表达式中的函数,所以binding.value()
                    * 就是用来执行当前上下文methods中指定的函数的。
                    * */
                    if (binding.expression) {
                        binding.value(e)
                    }
                }
    
                /*与Vue 1.0不同的是,在自定义指令中,不能再使用this.xxx的形式再上下
                文中声明一个变量,所以用了el.__vueMenuHandler__引用了documentHandler,
                这样就可以再unbind钩子里移除对document的click
                事件监听。如果不移除,当组建或元素销毁时,它任然存在于内存中。
                * */
                el.__vueMenuHandler__ = documentHandler;
                document.addEventListener('click', el.__vueMenuHandler__)
            },
            unbind(el) {
                document.removeEventListener('click', el.__vueMenuHandler__)
                delete el.__vueMenuHandler__
            }
        })
        new Vue({
            el: '#app',
            data: {
                show: false
            },
            methods: {
                handleHide() {
                    this.show = false
                }
            }
        })
    </script>
    </body>
    </html>
    相对时间转换
    在很多社区网站,比如朋友圈、微博等,发布的动态有一个相对本机时间转换后的相对时间。
    我们来实现这样一个Vue自定义指令v-time,将表达式传入的时间戳实时转换为相对时间
    index.js代码如下
    var vm = new Vue({
        el: '#app',
        data: {
            timeNow: (new Date()).getTime(),
            timeBefore: 1580503571085
        }
    })
    
    timeNow是当前的时间,
    timeBefore是一个写死的时间:2020-02-01
    在写指令v-time之前,需要先写一系列与时间相关的函数 ,我们声明一个对象Time,把它们都封装到里面。
    time.js代码如下:
    
    var Time = {
        //获取当前时间戳
        getUnix: function() {
            var date = new Date();
            return date.getTime();
        },
    
    //获取今天0点0分0秒的时间戳
    getTodayUnix: function() {
        var date = new Date();
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setMilliseconds(0);
        return date.getTime();
    },
    
    //获取今年1月1日0点0秒的时间戳
    getYearUnix: function() {
        var date = new Date();
        date.setMonth(0);
        date.setDate(1);
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setMilliseconds(0);
        return date.getTime();
    },
    //获取标准年月日
    getLastDate: function(time) {
        var date = new Date(time);
        var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
        var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
        return date.getFullYear() + '-' + month + '-' + day;
    },
    //转换时间
    getFormateTime: function(timestamp) {
        var now = this.getUnix();
        var today = this.getTodayUnix();
        var year = this.getYearUnix();
        var timer = (now - timestamp) / 1000;
        var tip = '';
    
        if (timer <= 0) {
            tip = '刚刚';
        } else if (Math.floor(timer / 60) <= 0) {
            tip = '刚刚';
        } else if (timer < 3600) {
            tip = Math.floor(timer / 60) + '分钟前';
        } else if (timer >= 3600 && (timestamp - today >= 0)) {
            tip = Math.floor(timer / 3600) + '小时前';
        } else if (timer / 86400 <= 31) {
            tip = Math.ceil(timer / 86400) + '天前';
        } else {
            tip = this.getLastDate(timestamp);
        }
        return tip;
    }
    }
    Time.getFormatTime()方法就是自定义指令v-time所需要的,参数为毫秒级时间戳,返回已经整理好的时间格式的字符串。
    最后在time.js里补全剩余的代码如下:
     Vue.directive('time', {
        bind: function(el,binding) {
            el.innerHTML = Time.getFormateTime(binding.value);
            el.__timeout__ = setInterval(() => {
                el.innerHTML = Time.getFormateTime(binding.value);
            },60000);
        },
        unbind: function() {
            clearInterval(el.__timeout__);
            delete el.__timeout__;
        }
    })
    
    在bind钩子里,将指令v-time表达式的值binding.value作为参数传入Time.getFormatTime()方法中得到格式化时间,在通过el.innerHTML写入指令所在元素。定时器el.__timeout__每分钟触发一次,更新时间,并且在unbind钩子里清除掉。
    <!DOCTYPE html>
    <html>
    <head>
        <title>时间转换指令</title>
        <meta charset="utf-8"/>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <div v-time="timeNow"></div>
        <div v-time="timeBefore"></div>
    </div>
    <script src="./time.js"></script>
    <script src="./index.js"></script>
    </body>
    </html>
  • 相关阅读:
    angular 1.26 版本 window.history.back() 自动去顶部
    CK editor 制作 ”小“plugin
    CSS 3 过渡效果之jquery 的fadeIn ,fadeOut
    了解 : angular controller link nginit 顺序
    规范 : jobbox 中英文
    了解 : angular translate 和 google translate 和 微软 translate
    业务逻辑 : 未完 : easybook.com
    List和ArrayList的区别
    Select什么时候会产生重作日志
    几点对专用服务器与共享服务器差异的理解
  • 原文地址:https://www.cnblogs.com/tszr/p/15395366.html
Copyright © 2011-2022 走看看