Base
In addition to built-in directives, Vue.js also allows registration of custom directives. Custom directives provide a mechanism to map changes in data into DOM behavior.
A global custom directive can be registered using the Vue.directive(id, definition) method, which receives two parameter instruction IDs and definition objects. You can also register a local custom directive using the component's directives option.
Hook function
Defining an object can provide several hook functions (all optional):
•bind: Called only once, and is called when the instruction is bound to the element for the first time.
•update: The first call is called immediately after bind with the initial value as the parameter, and then whenever the bound value changes, the parameters are the new value and the old value.
•unbind: Called only once, when the instruction is unbined from the element.
Example
Vue.directive('my-directive', { bind: function () { // Preparation work // For example, adding an event processor or a high-consuming task that only needs to be run once}, update: function (newValue, oldValue) { // Work when value is updated// It will also be called once with the initial value as a parameter}, unbind: function () { // Cleaning work // For example, delete the event listener added by bind() }})After registering, you can use it like this in the Vue.js template (remember to add the prefix v-):
<div v-my-directive="someValue"></div>
When only the update function is needed, you can pass in a function instead of the definition object:
Vue.directive('my-directive', function (value) { // This function is used as update()})Directive instance properties
All hook functions will be copied into the actual directive object, and this inside the hook points to this directive object. This object exposes some useful properties:
•el: The element bound to the directive.
•vm: The context ViewModel that owns the instruction.
•expression: The expression of the directive, excluding parameters and filters.
•arg: Parameters of the directive.
•name: The name of the directive, without prefix.
•modifiers: An object containing modifiers for directives.
•descriptor: An object containing the parsing results of a directive.
You should treat these properties as read-only and do not modify them. You can also add custom properties to the directive object, but be careful not to overwrite existing internal properties.
Example:
<div id="demo" v-demo:hello.ab="msg"></div>
Vue.directive('demo', { bind: function () { console.log('demo bound!') }, update: function (value) { this.el.innerHTML = 'name - ' + this.name + '<br>' + 'expression - ' + this.expression + '<br>' + 'argument - ' + this.arg + '<br>' + 'modifiers - ' + JSON.stringify(this.modifiers) + '<br>' + 'value - ' + value }})var demo = new Vue({ el: '#demo', data: { msg: 'hello!' }})Object literal
If the directive requires multiple values, you can pass in a JavaScript object literal. Remember that directives can use any legal JavaScript expression:
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
Vue.directive('demo', function (value) { console.log(value.color) // "white" console.log(value.text) // "hello!"})Literal modifier
When the directive uses a literal modifier, its value will be processed as a normal string and passed to the update method. The update method will be called only once, because a normal string cannot respond to data changes.
<div v-demo.literal="foo bar baz">
Vue.directive('demo', function (value) { console.log(value) // "foo bar baz"})Elemental Directive
Sometimes we want to use directives in the form of custom elements, not in the form of features. This is very similar to Angular's "E" directive. Element instructions can be regarded as a lightweight component. You can register a custom element directive like the following:
Vue.elementDirective('my-directive', { // API bind: function () { // Operation this.el... }})Don't write like this:
<div v-my-directive></div>
Write this way:
<my-directive></my-directive>
An element instruction cannot accept parameters or expressions, but it can read the characteristics of an element to determine its behavior.
Unlike ordinary instructions, element instructions are final, which means that once Vue encounters an element instruction, it will skip the element and its child elements - only the element instruction itself can operate on the element and its child elements.
Advanced Options
params
Custom directives can receive a params array, specifying a list of features, and the Vue compiler will automatically extract these features of the bound elements. For example:
<div v-example a="hi"></div>
Vue.directive('example', { params: ['a'], bind: function () { console.log(this.params.a) // -> "hi" }})This API also supports dynamic properties. this.params[key] will be automatically updated. In addition, a callback can be specified to call when the value changes:
<div v-example v-bind:a="someValue"></div>
Vue.directive('example', { params: ['a'], paramWatchers: { a: function (val, oldVal) { console.log('a changed!') } }})Similar to props, the name of the directive parameter uses camelCase style in JavaScript, and the kebab-case style is corresponding to the HTML. For example, suppose there is a parameter `disable-effect` in the template, access it in JavaScript with `disableEffect`.
deep
If a custom directive is used on an object and update is triggered when the internal properties of the object change, specify deep: true in the directive definition object.
<div v-my-directive="obj"></div>
Vue.directive('my-directive', { deep: true, update: function (obj) { // Called when the nested properties of `obj` change }})twoWay
If the directive wants to write back data to the Vue instance, specify twoWay: true in the directive definition object. This option allows this.set(value) to be used in directives:
Vue.directive('example', { twoWay: true, bind: function () { this.handler = function () { // Write data back to vm // If the directive binds v-example="abc" like this // It will set `vm.abc` with the given value this.set(this.el.value) }.bind(this) this.el.addEventListener('input', this.handler) }, unbind: function () { this.el.removeEventListener('input', this.handler) }})acceptStatement
Passing acceptStatement:true allows custom directives to accept inline statements, just like v-on:
<div v-my-directive="a++"></div>
Vue.directive('my-directive', { acceptStatement: true, update: function (fn) { // The incoming value is a function // The "a++" statement will be calculated within the scope of the belonging instance when it is called}})Use wisely because usually you want to avoid side effects in your template.
terminal
1.0.19+
Vue compiles modules by recursively traversing the DOM tree. But when it encounters a terminal directive it stops traversing the descendant elements of this element. This directive will take over the task of compiling this element and its descendants. v-if and v-for are terminal directives.
Writing custom terminal directives is a high-level topic and requires a better understanding of Vue's compilation process, but this does not mean that it is impossible to write custom terminal directives. Use terminal: true to specify a custom terminal directive, and may also need to use Vue.FragmentFactory to compile partial. Here is a custom terminal directive that compiles its content template and injects the results into another place on the page:
var FragmentFactory = Vue.FragmentFactoryvar remove = Vue.util.removevar createAnchor = Vue.util.createAnchorVue.directive('inject', { terminal: true, bind: function () { var container = document.getElementById(this.arg) this.anchor = createAnchor('v-inject') container.appendChild(this.anchor) remove(this.el) var factory = new FragmentFactory(this.vm, this.el) this.frag = factory.create(this._host, this._scope, this._frag) this.frag.before(this.anchor) }, unbind: function () { this.frag.remove() remove(this.anchor) }})<div id="modal"></div>...<div v-inject:modal> <h1>header</h1> <p>body</p> <p>footer</p></div>
If you want to write custom terminal directives, it is recommended that you read through the source code of built-in terminal directives, such as v-if and v-for, so as to better understand Vue's internal mechanisms.
priority
You can assign a priority to the instruction. If not specified, the default for normal command is 1000, and the default for terminal command is 2000. Instructions with higher priority on the same element will be processed earlier than other instructions. Directives with the same priority are processed in the order in which they appear in the element property list, but it cannot be guaranteed that this order is consistent in different browsers.
The priority of built-in directives can be viewed in the API. In addition, the process control instructions v-if and v-for always have the highest priority during the compilation process.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.