10 Vue Custom Directive

Why use custom instructions

  • In vue2, the main form of code reuse and abstraction is component.However, in some cases, we still need to do a bottom level operation on common DOM elements, when we use custom instructions
  • In addition to the built-in instructions (v-for/v-if/v-else/v-else-if/v-model/v-bind/v-on/v-show/v-text...Vue. js also allows you to register custom instructions.
  • Custom directives provide a mechanism to map changes in data to DOM behavior.
  • You can register a global custom instruction with the vue.directive(id, definition) method, which receives two parameter instruction IDs and a definition object.You can also register a local custom instruction with the directives option of the component.
An instruction definition object can provide the following hook functions (all optional):
  • bind: Called only once, the first time an instruction is bound to an element.Here you can make one-off initialization settings.
  • Inserted: Called when a bound element is inserted into a parent node (only the parent node is guaranteed to exist, but not necessarily inserted into the document).
  • update: Called when the VNode of the component is updated, but may occur before its child VNode is updated.The value of the instruction may or may not have changed.But you can ignore unnecessary template updates by comparing values before and after updates.
  • componentUpdated: Called after the VNode of the component in which the instruction resides and all its children are updated.
  • unbind: Called only once, when an instruction is unbound from an element.
<script>
// Definition
Vue.directive('my-directive', {
    bind: function () {
        // Dead work
        // For example, add an event handler or a power-consuming task that only needs to be run once
    },
    update: function(newValue, oldValue){
        // Work on value update
        // Also called once with an initial value as a parameter
    },
    unbind: function() {
        // Cleanup
        // For example, delete the event listener added by bind()
    }
})
</script>
<!-- Use -->
<div v-my-directive="someValue"></div>
The instruction hook function is passed in the following parameters:
  • el: An element bound to an instruction that can be used to directly manipulate the DOM.
  • binding: An object that contains the following properties:
    • Name: Instruction name, excluding the v-prefix.
    • Value: The bound value of an instruction, for example, in v-my-directive= "1 + 1", the bound value is 2.
    • oldValue: The previous value of the instruction binding, available only in the update and componentUpdate hooks.Whether the value changes or not is available.
    • Expression: An instruction expression in the form of a string.For example, in v-my-directive="1 + 1", the expression is "1 + 1".
    • arg: The parameter passed to the instruction, optional.For example, in v-my-directive:foo, the parameter is "foo".
    • Modifiers: An object containing modifiers.For example, in v-my-directive.foo.bar, the modifier object is {foo: true, bar: true}.
  • vnode:Vue Compile generated virtual node.Walk the VNode API for more details.
  • oldVnode: The last virtual node, available only in the update and componentUpdate hooks.
Dynamic Instruction Parameters

Instruction parameters can be dynamic.For example, in v-mydirective:[argument]="value", the argument parameter can be updated based on the component instance data!This allows custom instructions to be used flexibly in applications.

Function abbreviation

In many cases, you may want to trigger the same behavior when bind and update, regardless of the other hooks.For example, write:

Vue.directive('color-swatch', function (el, binding) {
  el.style.backgroundColor = binding.value
})
Object Literal

If the instruction requires more than one value, a JavaScript object literal quantity can be passed in.Remember, instruction functions can accept all legal JavaScript expressions.

<div v-demo="{ color: 'white', text: 'hello!' }"></div>
<script>
Vue.directive('demo', function (el, binding) {
  console.log(binding.value.color) // => "white"
  console.log(binding.value.text)  // => "hello!"
})
</script>

Familiarize yourself with custom instructions

Write time display plugin demo

Design sketch

file structure
|- js
|  |- time.js
|- index.html

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
    <script src="./js/time.js"></script>
</head>
<body>
    <div id="app">
        <div v-time="timeNow1"></div>
        <div v-time="timeNow2"></div>
        <div v-time="timeNow3"></div>
    </div>
    <script>
    var app = new Vue({
        el: "#app",
        data: {
            timeNow1: new Date().getTime() - 10 * 1000,// 10 seconds
            timeNow2: new Date().getTime() - 60 * 1000,// 1 minute
            timeNow3: new Date().getTime() - 60 * 1000 * 60// 1 hour
        }
    })
    </script>
</body>
</html>

js/time.js

var Time = {
    // Get the current timestamp
    getUnix:function () {
        var date = new Date();
        return date.getTime();
    },
    // Get a timestamp of 0:0 minutes and 0 seconds today
    getTodayUnix:function () {
        var date = new Date();
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setMilliseconds(0);
        return date.getTime();
    },
    // Get a timestamp of 0:0 min 0 seconds on January 1, this year
    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();
    },
    // Get Standard Year, Month and Day
    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;
    },
    // Conversion time
    getFormatTime:function (timestamp) {
        var now = this.getUnix(); // Current timestamp
        var today = this.getTodayUnix(); // Time stamp at 0 o'clock today
        var year = this.getYearUnix(); // Time stamp for 0 o'clock this year
        var timer = (now - timestamp) / 1000; // Time stamp converted to seconds
        var tip = '';

        if(timer <= 0){
            tip = 'just';
        }else if(Math.floor(timer/60) <= 0){
            tip = 'just';
        }else if(timer < 3600){
            tip = Math.floor(timer/60) + 'Minutes ago';
        }else if(timer >= 3600 && (timestamp - today >= 0)){
            tip = Math.floor(timer/3600) + 'Hours ago';
        }else if(timer/86400 <= 31){
            tip = Math.ceil(timer/86400) + 'Days ago';
        }else{
            tip = this.getLastDate(timestamp);
        }
        return tip;
    }
}

Vue.directive('time', {
    bind: function(el, binding){
        el.innerHTML = Time.getFormatTime(binding.value)
        el.timeOut = setInterval(function() {
            el.innerHTML = Time.getFormatTime(binding.value)
        }, 1000 * 10)// Detect once in ten seconds
    },
    unbind: function(el) {
        clearInterval(el.timeOut)
        delete el.timeOut
    }
})
54 original articles published, 18 praised, 5142 visits
Private letter follow

Tags: Vue Javascript

Posted on Mon, 10 Feb 2020 21:19:30 -0500 by lulon83