Directives and plugins are how you extend Vue itself, and how most Vue libraries are installed.
Composables reuse stateful logic; custom directives reuse low-level DOM manipulation on plain elements. A directive is an object of lifecycle hooks: created, beforeMount, mounted, beforeUpdate, updated, beforeUnmount, unmounted. Each receives (el, binding, vnode), where binding.value is the expression's value, binding.arg is the argument (v-tooltip:top gives 'top') and binding.modifiers is an object of modifiers.
In <script setup>, any camelCase variable starting with v is usable as a directive: const vFocus = { mounted: (el) => el.focus() } enables <input v-focus>. A function shorthand runs on both mounted and updated. Register globally with app.directive('focus', vFocus).
Prefer components or composables when possible; directives are for things like focus, click-outside, intersection observers and tooltips. They do not work well on components with multiple root nodes.
A plugin is an object with install(app, options) (or just a function). Inside it you can:
- register components and directives with
app.component/app.directive, - make values available with
app.provide(key, value), - add
app.config.globalProperties.$xfor template access (use sparingly), - set
app.config.errorHandleror other app config.
Users install it with app.use(plugin, options). Vue Router, Pinia and i18n libraries are all plugins.
Example
// clickOutside.js
export const vClickOutside = {
mounted(el, binding) {
el._onDocClick = (e) => {
if (!el.contains(e.target)) binding.value(e) // call the handler
}
document.addEventListener('click', el._onDocClick)
},
unmounted(el) {
document.removeEventListener('click', el._onDocClick)
},
}
// plugin.js
import { vClickOutside } from './clickOutside.js'
export const UiKit = {
install(app, { locale = 'en' } = {}) {
app.directive('click-outside', vClickOutside)
app.provide('ui-locale', locale)
},
}
// main.js: createApp(App).use(UiKit, { locale: 'fr' }).mount('#app')
// usage: <div v-click-outside="close" class="menu">...</div>Remember
- Directives are objects of hooks receiving
(el, binding); use them for DOM-level behaviour - In script setup,
vSomethingvariables are directives automatically - A plugin is
install(app, options); it registers components, directives and provides
Watch out for
- Forgetting to remove listeners in
unmounted, leaking handlers for every mounted element.