Skip to content

Commit 6db84d6

Browse files
authored
Merge pull request #4 from vuejs/dynamic-directive-arguments
Proposal for dynamic directive arguments
2 parents 62fad7d + 865a7e7 commit 6db84d6

File tree

1 file changed

+128
-0
lines changed

1 file changed

+128
-0
lines changed

Diff for: active-rfcs/0000-dynamic-directive-arguments.md

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
- Start Date: 2019-01-16
2+
- Target Major Version: (2.x / 3.x)
3+
- Reference Issues: https://github.com/vuejs/rfcs/pull/2, https://github.com/vuejs/rfcs/pull/3
4+
- Implementation PR: (leave this empty)
5+
6+
# Summary
7+
8+
Support dynamic values in directive arguments.
9+
10+
# Basic example
11+
12+
``` html
13+
<div v-bind:[key]="value"></div>
14+
<div v-on:[event]="handler"></div>
15+
```
16+
17+
# Motivation
18+
19+
Due to directive arguments being static, currently users would have to resort to argument-less object bindings in order to leverage dynamic keys:
20+
21+
``` html
22+
<div v-bind="{ [key]: value }"></div>
23+
<div v-on="{ [event]: handler }"></div>
24+
```
25+
26+
However, this has a few issues:
27+
28+
- It's a lesser known technique that relies on knowledge of the object-based syntax for `v-bind`/`v-on` and the existence of computed property keys in JavaScript.
29+
30+
- It generates less efficient code: an ad-hoc object is allocated and if there are other static bindings on the same element, it has to be dynamically iterated and mixed into the existing data object. The code looks roughly like this:
31+
32+
``` js
33+
return h('div', {
34+
on: Object.assign({
35+
click: onClick
36+
}, {
37+
[event]: handler
38+
})
39+
})
40+
```
41+
42+
Where as with dynamic arguments we can directly generate:
43+
44+
``` js
45+
return h('div', {
46+
on: {
47+
click: onClick,
48+
[event]: handler
49+
}
50+
})
51+
```
52+
53+
In addition, `v-slot` doesn't have an equivalent object syntax, since it's value is used for declaring the slot scope variable. So without the dynamic argument, the `v-slot` syntax will not be able to support dynamic slot names. Although this is probably a very rare use case, it would be a pain having to rewrite an entire template into render function just because of this single limitation.
54+
55+
# Detailed design
56+
57+
``` html
58+
<!-- v-bind with dynamic key -->
59+
<div v-bind:[key]="value"></div>
60+
61+
<!-- v-bind shorthand with dynamic key -->
62+
<div :[key]="value"></div>
63+
64+
<!-- v-on with dynamic event -->
65+
<div v-on:[event]="handler"></div>
66+
67+
<!-- v-on shorthand with dynamic event -->
68+
<div @[event]="handler"></div>
69+
70+
<!-- v-slot with dynamic name -->
71+
<foo>
72+
<template v-slot:[name]>
73+
Hello
74+
</template>
75+
</foo>
76+
77+
<!-- v-slot shorthand with dynamic name -->
78+
<!-- pending #3 -->
79+
<foo>
80+
<template #[name]>
81+
Default slot
82+
</template>
83+
</foo>
84+
```
85+
86+
### Handling of `null` as Special Value
87+
88+
Dynamic argument values are expected to be strings. However, it would be convenient if we allow `null` as a special value that explicitly indicates that the binding should be removed. Any other non-string values are likely mistakes and will trigger a warning.
89+
90+
`null` as a special value only applies to `v-bind` and `v-on`, but not `v-slot`. This is because `v-slot` is not a binding and cannot be removed. Custom directives have the liberty of deciding how to handle non-string arguments, but are expected to follow the convention when it applies.
91+
92+
# Drawbacks / Considerations
93+
94+
### Constraints on expressions
95+
96+
Theoretically this opens up the directive argument to arbitrarily complex JavaScript expressions, but html attribute names cannot contain spaces and quotes, so in some cases the user may get tripped up with something like:
97+
98+
``` html
99+
<div :[key + 'foo']="value"></div>
100+
```
101+
102+
Which does not work as expected. A workaround would be:
103+
104+
``` html
105+
<div :[`key${foo}`]="value"></div>
106+
```
107+
108+
That said, complex dynamic key bindings should probably be pre-transformed in JavaScript via a computed property.
109+
110+
**Update:**: it is possible to detect such usage and provide proper warnings in the parser (by checking for arguments that are missing the closing bracket).
111+
112+
### Custom Directives
113+
114+
Allowing dynamic arguments for all directives means custom directive implementations now also need to account for potential argument changes in addition to value changes.
115+
116+
This also requires the addition of `binding.oldArgs` to the custom directive binding context.
117+
118+
# Alternatives
119+
120+
N/A
121+
122+
# Adoption strategy
123+
124+
This is non-breaking and should be straightforward to introduce with appropriate documentation updates.
125+
126+
# Unresolved questions
127+
128+
N/A

0 commit comments

Comments
 (0)