Vue.js--Custom Instructions


http://www.jianshu.com/p/c2bef47439ab

Vue.js allows you to register custom instructions, essentially allowing you to teach Vue some new tricks: how to map changes in data to the behavior of the DOM.You can register a global custom instruction by passing in an instruction ID and a definition object using the Vue.directive(id, definition) method.Defining objects requires some hook functions (all optional):

  1. Bid: Called only once, when the instruction first bind s elements.
  2. update: The first call is immediately after the bind, and the parameter is the initial value of the binding; then every time the value of the binding changes, it is called to get two parameters, the new value and the old value.
  3. unbind: Called only once, when an instruction unbinds an element.

Example:

Vue.directive('my-directive', {
  bind: function () {
    // Preparing for binding
    // Add event listeners, for example, or other complex operations that only need to be performed once
  },
  update: function (newValue, oldValue) {
    // Perform the corresponding update based on the new value obtained
    // Also called once for the initial value
  },
  unbind: function () {
    // Clean up
    // For example, remove the event listener added in bind()
  }
})

Once you have registered your custom directives, you can use them like this in the Vue.js template (you need to add a Vue.js directive prefix, which defaults to v-):

<div v-my-directive="someValue"></div>

If you only need the update function, you can pass in only one function instead of defining an object:

Vue.directive('my-directive', function (value) {
  // This function will be used as the update() function
})

All hook functions are copied into the actual instruction object, which will be this for all hook functions
Context.Some useful public properties are exposed on the instruction object:

el:Element of instruction binding
vm: Context ViewModel that owns the directive
Expression: An expression of an instruction, excluding parameters and filters
arg:Parameters of instruction
raw:Unparsed original expression
Name:Unprefixed directive name

These properties are read-only, do not modify them.You can also attach custom attributes to the instruction object, but be careful not to overwrite existing internal attributes.

Example of using instruction object properties:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/vue/0.12.16/vue.min.js"></script>
</head>
<body>
<div id="demo" v-demo-directive="LightSlateGray : msg"></div>

<script>
    Vue.directive('demoDirective', {
        bind: function () {
            this.el.style.color = '#fff'
            this.el.style.backgroundColor = this.arg
        },
        update: function (value) {
            this.el.innerHTML =
                    'name - '       + this.name + '<br>' +
                    'raw - '        + this.raw + '<br>' +
                    'expression - ' + this.expression + '<br>' +
                    'argument - '   + this.arg + '<br>' +
                    'value - '      + value
        }
    });
    var demo = new Vue({
        el: '#demo',
        data: {
            msg: 'hello!'
        }
    })

</script>
</body>
</html>

Multiple Clauses

Within the same attribute, comma-separated clauses are bound to multiple instruction instances.In the following example, an instruction is created and invoked twice:

<div v-demo="color: 'white', text: 'hello!'"></div>

If you want to process multiple parameters with a single instruction instance, you can use a literal object as an expression:

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

Literal Instructions

If isLiteral: true is passed in when a custom instruction is created, the attribute value is treated as a direct string and assigned to the expression of the instruction.Literal instructions do not attempt to establish data monitoring.
Example:

<div v-literal-dir="foo"></div>
Vue.directive('literal-dir', {
  isLiteral: true,
  bind: function () {
    console.log(this.expression) // 'foo'
  }
})

Dynamic Literal Instructions

However, in the case where a literal instruction contains a Mustache tag, the instructions behave as follows:

The instruction instance has a property, this._isDynamicLiteral is set to true;

If the update function is not provided, the Mustache expression will only be evaluated once and assigned to this.expression.The expression will not be monitored for data.

If an update function is provided, the directive establishes a data monitor for the expression and calls update when the result of the calculation changes.

Bidirectional instruction

If your directive wants to write data back to the Vue instance, you need to pass in twoWay: true.This option allows this.set(value) to be used in instructions.

Vue.directive('example', {
  twoWay: true,
  bind: function () {
    this.handler = function () {
      // Write data back to vm
      // If the directive binds v-example="a.b.c"
      // This assigns a value to `vm.a.b.c`
      this.set(this.el.value)
    }.bind(this)
    this.el.addEventListener('input', this.handler)
  },
  unbind: function () {
    this.el.removeEventListener('input', this.handler)
  }
})

Inline statement

Passing in acceptStatement: true allows custom instructions to accept inline statements like v-on:

<div v-my-directive="a++"></div>
Vue.directive('my-directive', {
  acceptStatement: true,
  update: function (fn) {
    // the passed in value is a function which when called,
    // will execute the "a++" statement in the owner vm's
    // scope.
  }
})

However, use this function wisely, as we usually want to avoid side effects in templates.

Deep Data Observation

If you want to use custom instructions on an object and trigger the update function of the instructions when the nested attributes within the object change, you will pass deep: true into the definition of the instructions.

<div v-my-directive="obj"></div>
Vue.directive('my-directive', {
  deep: true,
  update: function (obj) {
    // This function is also called when nested attributes within obj change
  }
})

Instruction Priority

You can choose to give the instruction a priority number (default is 0).Instructions with higher priority on the same element are processed earlier than others.Instructions with the same priority are processed in the order in which they appear in the list of element attributes, but this order is not guaranteed to be consistent across browsers.

Usually, as a user, you don't need to care about the priority of built-in instructions. If you're interested, you can refer to the source code.Logical control directives v-repeat and V-IF are considered "final directives" and always have the highest priority during compilation.

Element directives

Sometimes, we might want our instructions to be used as custom elements, not as a feature.This is very similar to the concept of Angular's class E directive.Element directives can be thought of as a lightweight custom component (described later).You can register a custom element instruction as follows:

Vue.elementDirective('my-directive', {
  // Consistent with API of Common Instruction
  bind: function () {
    // Operate on this.el...
  }
})

We no longer use this notation when using:

<div v-my-directive></div>

Instead, it says:

<my-directive></my-directive>

Element directives cannot accept parameters or expressions, but they can read an element's attributes to determine its behavior.Unlike normal instructions, element directives are final, meaning that once a Vue encounters an element directive, it skips compiling the element and its children - that is, only the element directive itself can operate on the element and its children.

Keywords: Vue Attribute angular

Added by waylon999 on Sun, 14 Jul 2019 19:42:30 +0300