- Getting Started
- The Vue Instance
- Data Binding Syntax
- Computed Properties
- Class and Style Bindings
- Conditional Rendering
- List Rendering
- Methods and Event Handling
- Form Input Bindings
- Reactivity in Depth
- Custom Directives
- Custom Filters
- Building Large-Scale Apps
- Comparison with Other Frameworks
- Join the Vue Community!
In addition to the default set of directives shipped in core, Vue.js also allows you to register custom directives. Custom directives provide a mechanism for mapping data changes to arbitrary DOM behavior.
You can register a global custom directive with the
Vue.directive(id, definition) method, passing in a directive id followed by a definition object. You can also register a local custom directive by including it in a component’s
A definition object can provide several hook functions (all optional):
bind: called only once, when the directive is first bound to the element.
update: called for the first time immediately after
bindwith the initial value, then again whenever the binding value changes. The new value and the previous value are provided as the argument.
unbind: called only once, when the directive is unbound from the element.
Once registered, you can use it in Vue.js templates like this (remember to add the
When you only need the
update function, you can pass in a single function instead of the definition object:
Directive Instance Properties
All the hook functions will be copied into the actual directive object, which you can access inside these functions as their
this context. The directive object exposes some useful properties:
- el: the element the directive is bound to.
- vm: the context ViewModel that owns this directive.
- expression: the expression of the binding, excluding arguments and filters.
- arg: the argument, if present.
- name: the name of the directive, without the prefix.
- modifiers: an object containing modifiers, if any.
- descriptor: an object that contains the parsing result of the entire directive.
- params: an object containing param attributes. Explained below.
You should treat all these properties as read-only and never modify them. You can attach custom properties to the directive object too, but be careful not to accidentally overwrite existing internal ones.
An example of a custom directive using some of these properties:
When a directive is used with the literal modifier, its attribute value will be interpreted as a plain string and passed directly into the
update method. The
update method will also be called only once, because a plain string cannot be reactive.
In some cases, we may want our directive to be used in the form of a custom element rather than as an attribute. This is very similar to Angular’s notion of “E” mode directives. Element directives provide a lighter-weight alternative to full-blown components (which are explained earlier in the guide). You can register a custom element directive like so:
Then, instead of:
We can write:
Element directives cannot accept arguments or expressions, but it can read the element’s attributes to determine its behavior.
A big difference from normal directives is that element directives are terminal, which means once Vue encounters an element directive, it will completely skip that element - only the element directive itself will be able to manipulate that element and its children.
Custom directive can provide a
params array, and the Vue compiler will automatically extract these attributes on the element that the directive is bound to. Example:
This API also supports dynamic attributes. The
this.params[key] value is automatically kept up-to-date. In addition, you can specify a callback when the value has changed:
disable-effect in the template, you need to access it as
If your custom directive is expected to be used on an Object, and it needs to trigger
update when a nested property inside the object changes, you need to pass in
deep: true in your directive definition.
If your directive expects to write data back to the Vue instance, you need to pass in
twoWay: true. This option allows the use of
this.set(value) inside the directive:
acceptStatement:true enables your custom directive to accept inline statements like
Use this wisely though, because in general you want to avoid side-effects in your templates.
Vue compiles templates by recursively walking the DOM tree. However when it encounters a terminal directive, it will stop walking that element’s children. The terminal directive takes over the job of compiling the element and its children. For example,
v-for are both terminal directives.
Writing a custom terminal directive is an advanced topic and requires decent knowledge of Vue’s compilation pipeline, but it’s possible. You can specify a custom terminal directive by specifying
terminal: true. You will also likely need to use
Vue.FragmentFactory for partial compilation. Here’s an example of a custom terminal directive that compiles and “injects” its content template to another location on the page:
If you want to write a custom terminal directive, it is recommend that you read through the source code of built-in terminal directives like
v-for to get a better understanding of Vue internals.
You can optionally provide a priority number for your directive. If no priority is specified, a default priority will be used -
1000 for normal directives and
2000 for terminal directives. A directive with a higher priority will be processed earlier than other directives on the same element. Directives with the same priority will be processed in the order they appear in the element’s attribute list, although that order is not guaranteed to be consistent in different browsers.
You can checkout the priorities for some built-in directives in the API reference. Additionally, flow control directives
v-for always have the highest priority in the compilation process.