Skip to content

Commit

Permalink
docs (#2914): fix autofocus issue on custom directives
Browse files Browse the repository at this point in the history
  • Loading branch information
bencodezen committed Sep 5, 2024
1 parent 6d4e543 commit 10fc360
Showing 1 changed file with 77 additions and 23 deletions.
100 changes: 77 additions & 23 deletions src/guide/reusability/custom-directives.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
# Custom Directives {#custom-directives}

<script setup>
const vFocus = {
const vHighlight = {
mounted: el => {
el.focus()
el.classList.add('is-highlight')
}
}
</script>

<style>
.vt-doc p.is-highlight {
margin-bottom: 0;
}

.is-highlight {
background-color: yellow;
color: black;
}
</style>

## Introduction {#introduction}

In addition to the default set of directives shipped in core (like `v-model` or `v-show`), Vue also allows you to register your own custom directives.
Expand All @@ -20,14 +31,16 @@ A custom directive is defined as an object containing lifecycle hooks similar to

```vue
<script setup>
// enables v-focus in templates
const vFocus = {
mounted: (el) => el.focus()
// enables v-highlight in templates
const vHighlight = {
mounted: (el) => {
el.classList.add('is-highlight')
}
}
</script>
<template>
<input v-focus />
<p v-highlight>This sentence is important!</p>
</template>
```

Expand All @@ -36,44 +49,42 @@ const vFocus = {
<div class="options-api">

```js
const focus = {
mounted: (el) => el.focus()
const highlight = {
mounted: (el) => el.classList.add('is-highlight')
}

export default {
directives: {
// enables v-focus in template
focus
// enables v-highlight in template
highlight
}
}
```

```vue-html
<input v-focus />
<p v-highlight>This sentence is important!</p>
```

</div>

<div class="demo">
<input v-focus placeholder="This should be focused" />
<p v-highlight>This sentence is important!</p>
</div>

Assuming you haven't clicked elsewhere on the page, the input above should be auto-focused. This directive is more useful than the `autofocus` attribute because it works not just on page load - it also works when the element is dynamically inserted by Vue.

<div class="composition-api">

In `<script setup>`, any camelCase variable that starts with the `v` prefix can be used as a custom directive. In the example above, `vFocus` can be used in the template as `v-focus`.
In `<script setup>`, any camelCase variable that starts with the `v` prefix can be used as a custom directive. In the example above, `vHighlight` can be used in the template as `v-highlight`.

If not using `<script setup>`, custom directives can be registered using the `directives` option:
If you are not using `<script setup>`, custom directives can be registered using the `directives` option:

```js
export default {
setup() {
/*...*/
},
directives: {
// enables v-focus in template
focus: {
// enables v-highlight in template
highlight: {
/* ... */
}
}
Expand All @@ -94,14 +105,58 @@ It is also common to globally register custom directives at the app level:
const app = createApp({})

// make v-focus usable in all components
app.directive('focus', {
app.directive('highlight', {
/* ... */
})
```

:::tip
Custom directives should only be used when the desired functionality can only be achieved via direct DOM manipulation. Prefer declarative templating using built-in directives such as `v-bind` when possible because they are more efficient and server-rendering friendly.
:::
## When to use custom directives {#when-to-use}

Custom directives should only be used when the desired functionality can only be achieved via direct DOM manipulation.

A common example of this is a `v-focus` custom directive that brings an element into focus.

<div class="composition-api">

```vue
<script setup>
// enables v-focus in templates
const vFocus = {
mounted: (el) => el.focus()
}
</script>
<template>
<input v-focus />
</template>
```

</div>

<div class="options-api">

```js
const focus = {
mounted: (el) => el.focus()
}

export default {
directives: {
// enables v-focus in template
focus
}
}
```

```vue-html
<input v-focus />
```

</div>

This directive is more useful than the `autofocus` attribute because it works not just on page load - it also works when the element is dynamically inserted by Vue!

Declarative templating with built-in directives such as `v-bind` is recommended when possible because they are more efficient and server-rendering friendly.

## Directive Hooks {#directive-hooks}

Expand Down Expand Up @@ -214,7 +269,6 @@ app.directive('demo', (el, binding) => {
Using custom directives on components is not recommended. Unexpected behaviour may occur when a component has multiple root nodes.
:::


When used on components, custom directives will always apply to a component's root node, similar to [Fallthrough Attributes](/guide/components/attrs).

```vue-html
Expand Down

0 comments on commit 10fc360

Please # to comment.