|
| 1 | +- Start Date: 01-16-2019 |
| 2 | +- Target Major Version: (2.x / 3.x) |
| 3 | +- Reference Issues: https://github.com/vuejs/rfcs/pull/2 |
| 4 | +- Implementation PR: (leave this empty) |
| 5 | + |
| 6 | +# Summary |
| 7 | + |
| 8 | +Add shorthand syntax for the `v-slot` syntax proposed in [rfc-0001](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0001-new-slot-syntax.md). Please make sure to read it first to get proper context for this proposal. |
| 9 | + |
| 10 | +# Basic example |
| 11 | + |
| 12 | +``` html |
| 13 | +<foo #="{ msg }"> |
| 14 | + {{ msg }} |
| 15 | +</foo> |
| 16 | + |
| 17 | + <foo> |
| 18 | + <template #header="{ msg }"> |
| 19 | + Message from header: {{ msg }} |
| 20 | + </template> |
| 21 | + |
| 22 | + <template #footer> |
| 23 | + A static footer |
| 24 | + </template> |
| 25 | +</foo> |
| 26 | +``` |
| 27 | + |
| 28 | +# Motivation |
| 29 | + |
| 30 | +A shorthand, as the name entails, primarily aims to provide more succinct syntax. |
| 31 | + |
| 32 | +In Vue we currently provide shorthands only for two directives: `v-bind` and `v-on`: |
| 33 | + |
| 34 | +``` html |
| 35 | +<div v-bind:id="id"></div> |
| 36 | +<div :id="id"></div> |
| 37 | + |
| 38 | +<button v-on:click="onClick"></div> |
| 39 | +<button @click="onClick"></div> |
| 40 | +``` |
| 41 | + |
| 42 | +`v-bind` and `v-on` often get used repeatedly on the same element, and can get verbose when the information differing between each is **the directive argument** instead of the directive itself. **Shorthands thus help improve the signal/noise ratio by shortening the parts that are duplicated (`v-xxx`) and highlighting the parts that are different (the arguments).** |
| 43 | + |
| 44 | +The new `v-slot` syntax can also get the same problem in components that expect multiple slots: |
| 45 | + |
| 46 | +``` html |
| 47 | +<TestComponent> |
| 48 | + <template v-slot:one="{ name }">Hello {{ name }}</template> |
| 49 | + <template v-slot:two="{ name }">Hello {{ name }}</template> |
| 50 | + <template v-slot:three="{ name }">Hello {{name }}</template> |
| 51 | +</TestComponent> |
| 52 | +``` |
| 53 | + |
| 54 | +Here `v-slot` is repeated multiple times where the actual differing part is the slot name (denoted by the argument). |
| 55 | + |
| 56 | +The shorthand helps slot names to be more easily scan-able: |
| 57 | + |
| 58 | +``` html |
| 59 | +<TestComponent> |
| 60 | + <template #one="{ name }">Hello {{ name }}</template> |
| 61 | + <template #two="{ name }">Hello {{ name }}</template> |
| 62 | + <template #three="{ name }">Hello {{name }}</template> |
| 63 | +</TestComponent> |
| 64 | +``` |
| 65 | + |
| 66 | +# Detailed design |
| 67 | + |
| 68 | +The shorthand follows very similar rules to the shorthand of `v-bind` and `v-on`: replace the directive name plus the colon with the shorthand symbol (`#`). |
| 69 | + |
| 70 | +For default slot on component: |
| 71 | + |
| 72 | +``` html |
| 73 | +<!-- full syntax --> |
| 74 | +<foo v-slot="{ msg }"> |
| 75 | + {{ msg }} |
| 76 | +</foo> |
| 77 | + |
| 78 | +<!-- shorthand --> |
| 79 | +<foo #="{ msg }"> |
| 80 | + {{ msg }} |
| 81 | +</foo> |
| 82 | +``` |
| 83 | + |
| 84 | +For named slots: |
| 85 | + |
| 86 | +``` html |
| 87 | +<!-- full syntax --> |
| 88 | +<foo> |
| 89 | + <template v-slot:header="{ msg }"> |
| 90 | + Message from header: {{ msg }} |
| 91 | + </template> |
| 92 | + |
| 93 | + <template v-slot:footer> |
| 94 | + A static footer |
| 95 | + </template> |
| 96 | +</foo> |
| 97 | + |
| 98 | +<!-- shorthand --> |
| 99 | +<foo> |
| 100 | + <template #header="{ msg }"> |
| 101 | + Message from header: {{ msg }} |
| 102 | + </template> |
| 103 | + |
| 104 | + <template #footer> |
| 105 | + A static footer |
| 106 | + </template> |
| 107 | +</foo> |
| 108 | +``` |
| 109 | + |
| 110 | +The choice of `#` is a selection based on the feedback collected in the previous RFC. It holds a resemblance to the id selector in CSS and translates quite well conceptually to stand for a slot's name. |
| 111 | + |
| 112 | +Some example usage in a real-world library that relies on scoped slots ([vue-promised](https://github.com/posva/vue-promised)): |
| 113 | + |
| 114 | + ``` html |
| 115 | +<Promised :promise="usersPromise"> |
| 116 | + <template #pending> |
| 117 | + <p>Loading...</p> |
| 118 | + </template> |
| 119 | + |
| 120 | + <template #="users"> |
| 121 | + <ul> |
| 122 | + <li v-for="user in users">{{ user.name }}</li> |
| 123 | + </ul> |
| 124 | + </template> |
| 125 | + |
| 126 | + <template #rejected="error"> |
| 127 | + <p>Error: {{ error.message }}</p> |
| 128 | + </template> |
| 129 | +</Promised> |
| 130 | +``` |
| 131 | + |
| 132 | +# Drawbacks |
| 133 | + |
| 134 | +- The `#` symbol doesn't translate that well conceptually when used on a component for default slot: |
| 135 | + |
| 136 | + ``` html |
| 137 | + <foo #="{ msg }"> |
| 138 | + {{ msg }} |
| 139 | + </foo> |
| 140 | + ``` |
| 141 | + |
| 142 | + Maybe we only support the shorthand for named slots? For default slot usage on component, full `v-slot` usage is required. It would also be consistent with `v-on` and `v-bind` where the shorthand does not apply if there is no argument. |
| 143 | + |
| 144 | +- Some may argue that slots are not that commonly used and therefore don't really need a shorthand, and it could result in extra learning curve for beginners. In response to that: |
| 145 | + |
| 146 | + 1. I believe scoped slot is an important mechanism for building 3rd party component suites that are highly customizable and composable. I think we will see more component libraries relying on slots for customization and composition in the future. For a user using such a component library, a shorthand will become quite valuable (as demonstrated in the examples). |
| 147 | + |
| 148 | + 2. The translation rules for the shorthand is straightforward and consistent with existing shorthands. If the user learns how the base syntax works, understanding the shorthand is a minimal extra step. |
| 149 | + |
| 150 | +# Alternatives |
| 151 | + |
| 152 | +Some alternative symbols have been presented and discussed in the previous RFC. The only other one with similarly positive interest is `&`: |
| 153 | + |
| 154 | +``` html |
| 155 | +<foo &="{ msg }"> |
| 156 | + {{ msg }} |
| 157 | +</foo> |
| 158 | + |
| 159 | + <foo> |
| 160 | + <template &header="{ msg }"> |
| 161 | + Message from header: {{ msg }} |
| 162 | + </template> |
| 163 | + |
| 164 | + <template &footer> |
| 165 | + A static footer |
| 166 | + </template> |
| 167 | +</foo> |
| 168 | +``` |
| 169 | + |
| 170 | +# Adoption strategy |
| 171 | + |
| 172 | +This should be a natural extension on top of the new `v-slot` syntax. Ideally, we'd want introduce the base syntax and the shorthand at the same time so users learn both at the same time. Introducing the shorthand at a later time runs the risk of some users only aware of the `v-slot` syntax and get confused when seeing the shorthand in others' code. |
| 173 | + |
| 174 | +# Unresolved questions |
| 175 | + |
| 176 | +- See Drawbacks No.1. |
0 commit comments