Skip to content

Commit a2fb970

Browse files
authored
Custom Directive API Change (#32)
1 parent 83d8780 commit a2fb970

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
- Start Date: 2019-04-09
2+
- Target Major Version: 3.x
3+
- Reference Issues: N/A
4+
- Implementation PR: N/A
5+
6+
# Summary
7+
8+
- Re-design custom directive API so that it better aligns with component lifecycle
9+
10+
- Custom directives usage on components will follow the same rules as discussed in the [Attribute Fallthrough Behavior RFC](https://github.com/vuejs/rfcs/pull/26). It will be controlled by the child component via `v-bind="$attrs"`.
11+
12+
# Basic example
13+
14+
## Before
15+
16+
``` js
17+
const MyDirective = {
18+
bind(el, binding, vnode, prevVnode) {},
19+
inserted() {},
20+
update() {},
21+
componentUpdated() {},
22+
unbind() {}
23+
}
24+
```
25+
26+
## After
27+
28+
``` js
29+
const MyDirective = {
30+
beforeMount(el, binding, vnode, prevVnode) {},
31+
mounted() {},
32+
beforeUpdate() {},
33+
updated() {},
34+
beforeUnmount() {}, // new
35+
unmounted() {}
36+
}
37+
```
38+
39+
# Motivation
40+
41+
Make custom directive hook names more consistent with the component lifecycle.
42+
43+
# Detailed design
44+
45+
## Hooks Renaming
46+
47+
Existing hooks are renamed to map better to the component lifecycle, with some timing adjustments. Arguments passed to the hooks remain unchanged.
48+
49+
- `bind` -> `beforeMount`
50+
- `inserted` -> `mounted`
51+
- `beforeUpdate` *new, called before the element itself is updated*
52+
- ~~`update`~~ *removed, use `updated` instead*
53+
- `componentUpdated` -> `updated`
54+
- `beforeUnmount` *new*
55+
- `unbind` -> `unmounted`
56+
57+
## Usage on Components
58+
59+
In 3.0, with fragments support, components can potentially have more than one root nodes. This creates an issue when a custom directive is used on a component with multiple root nodes.
60+
61+
To explain the details of how custom directives will work on components in 3.0, we need to first understand how custom directives are compiled in 3.0. For a directive like this:
62+
63+
``` html
64+
<div v-foo="bar"></div>
65+
```
66+
67+
Will roughly compile into this:
68+
69+
``` js
70+
const vFoo = resolveDirective('foo')
71+
72+
return withDirectives(h('div'), [
73+
[vFoo, bar]
74+
])
75+
```
76+
77+
Where `vFoo` will be the directive object written by the user, which contains hooks like `mounted` and `updated`.
78+
79+
`withDirectives` returns a cloned VNode with the user hooks wrapped and injected as vnode lifecycle hooks (see [Render Function API Changes](https://github.com/vuejs/rfcs/blob/render-fn-api-change/active-rfcs/0000-render-function-api-change.md#special-reserved-props) for more details):
80+
81+
``` js
82+
{
83+
onVnodeMounted(vnode) {
84+
// call vFoo.mounted(...)
85+
}
86+
}
87+
```
88+
89+
**As a result, custom directives are fully included as part of a VNode's data. When a custom directive is used on a component, these `onVnodeXXX` hooks are passed down to the component as extraneous props and end up in `this.$attrs`.**
90+
91+
This also means it's possible to directly hook into an element's lifecycle like this in the template, which can be handy when a custom directive is too involved:
92+
93+
``` html
94+
<div @vnodeMounted="myHook" />
95+
```
96+
97+
This is consistent with the attribute fallthrough behavior discussed in [vuejs/rfcs#26](https://github.com/vuejs/rfcs/pull/26). So, the rule for custom directives on a component will be the same as other extraneous attributes: it is up to the child component to decide where and whether to apply it. When the child component uses `v-bind="$attrs"` on an inner element, it will apply any custom directives used on it as well.
98+
99+
# Drawbacks
100+
101+
N/A
102+
103+
# Alternatives
104+
105+
N/A
106+
107+
# Adoption strategy
108+
109+
- The renaming should be easy to support in the compat build
110+
- Codemod should also be straightforward
111+
- For directives used on components, the warning on unused `$attrs` as discussed in [Attribute Fallthrough Behavior](https://github.com/vuejs/rfcs/pull/26) should apply as well.
112+
113+
# Unresolved questions
114+
115+
N/A

0 commit comments

Comments
 (0)