diff --git a/src/.vuepress/config.js b/src/.vuepress/config.js index d63c785b49..2b6e141773 100644 --- a/src/.vuepress/config.js +++ b/src/.vuepress/config.js @@ -91,7 +91,8 @@ const sidebar = { 'migration/global-api', 'migration/treeshaking', 'migration/functional-components', - 'migration/async-components' + 'migration/async-components', + 'migration/custom-directives' ] }, { diff --git a/src/guide/migration.md b/src/guide/migration.md index 550c461aee..a5979610df 100644 --- a/src/guide/migration.md +++ b/src/guide/migration.md @@ -92,104 +92,3 @@ Using the example from before, it can now be simplified to: ``` By passing our prop title to the `v-model` directive, Vue will listen for an `onUpdate:title` event that will be emitted from the child component in order to update the data accordingly. - -## Custom Directives - -### Custom Directive Lifecycle API - -Abstractions can be incredibly powerful to development, but they tend to break down when there is no escape hatch or extension beyond the original implementation. Custom directives allow us to create directives that are unique to our application. - -Previously, we constructed these directives by using the hooks listed below to target an element’s lifecycle, all of which are optional: - -- **bind** - Occurs once the directive is bound to the element. Occurs only once. -- **inserted** - Occurs once the element is inserted into the parent DOM. -- **update** - This hook is called when the element updates, but children haven't been updated yet. -- **componentUpdated** - This hook is called once the component and the children have been updated. -- **unbind** - This hook is called once the directive is removed. Also called only once. - -Here’s an example of this: - -```html -
Highlight this text bright yellow
-``` - -```js -Vue.directive('highlight', { - bind(el, binding, vnode) { - el.style.background = binding.value - } -}) -``` - -Here, in the initial setup for this element, the directive binds a style by passing in a value, that can be updated to different values through the application. - -In Vue 3, however, we’ve created a more cohesive API for custom directives. As you can see, they differ greatly from our component lifecycle methods even though we’re hooking into similar events. We’ve now unified them like so: - -- bind → **beforeMount** -- inserted → **mounted** -- **beforeUpdate**: new! this is called before the element itself is updated, much like the component lifecycle hooks. -- update → removed! There were too many similarities to updated, so this is redundant. Please use updated instead. -- componentUpdated → **updated** -- **beforeUnmount** new! similar to component lifecycle hooks, this will be called right before an element is unmounted. -- unbind -> **unmounted** - -The final API is as follows: - -```js -const MyDirective = { - beforeMount(el, binding, vnode, prevVnode) {}, - mounted() {}, - beforeUpdate() {}, - updated() {}, - beforeUnmount() {}, // new - unmounted() {} -} -``` - -The resulting API could be used like this, mirroring the example from earlier: - -```html -Highlight this text bright yellow
-``` - -```js -Vue.directive('highlight', { - beforeMount(el, binding, vnode) { - el.style.background = binding.value - } -}) -``` - -Now that the custom directive lifecycle hooks mirror those of the components themselves, they become easier to reason about and remember! - -#### Implementation Details - -In Vue 3, we’re now supporting fragments, which allow us to return more than one DOM node per component. You can imagine how handy that is for something like a component with multiple lis or the children elements of a table: - -```html -<> -Highlight this text bright yellow
+``` + +```js +Vue.directive('highlight', { + bind(el, binding, vnode) { + el.style.background = binding.value + } +}) +``` + +Here, in the initial setup for this element, the directive binds a style by passing in a value, that can be updated to different values through the application. + +## Current Syntax + +In Vue 3, however, we’ve created a more cohesive API for custom directives. As you can see, they differ greatly from our component lifecycle methods even though we’re hooking into similar events. We’ve now unified them like so: + +- bind → **beforeMount** +- inserted → **mounted** +- **beforeUpdate**: new! this is called before the element itself is updated, much like the component lifecycle hooks. +- update → removed! There were too many similarities to updated, so this is redundant. Please use updated instead. +- componentUpdated → **updated** +- **beforeUnmount** new! similar to component lifecycle hooks, this will be called right before an element is unmounted. +- unbind -> **unmounted** + +The final API is as follows: + +```js +const MyDirective = { + beforeMount(el, binding, vnode, prevVnode) {}, + mounted() {}, + beforeUpdate() {}, + updated() {}, + beforeUnmount() {}, // new + unmounted() {} +} +``` + +The resulting API could be used like this, mirroring the example from earlier: + +```html +Highlight this text bright yellow
+``` + +```js +const app = Vue.createApp({}) + +app.directive('highlight', { + beforeMount(el, binding, vnode) { + el.style.background = binding.value + } +}) +``` + +Now that the custom directive lifecycle hooks mirror those of the components themselves, they become easier to reason about and remember! + +## Implementation Details + +In Vue 3, we're now supporting fragments, which allow us to return more than one DOM node per component. You can imagine how handy that is for something like a component with multiple lis or the children elements of a table: + +```html + +