|
| 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> |
| 14 | + <template #header="{ msg }"> |
| 15 | + Message from header: {{ msg }} |
| 16 | + </template> |
| 17 | + |
| 18 | + <template #footer> |
| 19 | + A static footer |
| 20 | + </template> |
| 21 | +</foo> |
| 22 | +``` |
| 23 | + |
| 24 | +# Motivation |
| 25 | + |
| 26 | +A shorthand, as the name entails, primarily aims to provide more succinct syntax. |
| 27 | + |
| 28 | +In Vue we currently provide shorthands only for two directives: `v-bind` and `v-on`: |
| 29 | + |
| 30 | +``` html |
| 31 | +<div v-bind:id="id"></div> |
| 32 | +<div :id="id"></div> |
| 33 | + |
| 34 | +<button v-on:click="onClick"></button> |
| 35 | +<button @click="onClick"></button> |
| 36 | +``` |
| 37 | + |
| 38 | +`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).** |
| 39 | + |
| 40 | +The new `v-slot` syntax can also get the same problem in components that expect multiple slots: |
| 41 | + |
| 42 | +``` html |
| 43 | +<TestComponent> |
| 44 | + <template v-slot:one="{ name }">Hello {{ name }}</template> |
| 45 | + <template v-slot:two="{ name }">Hello {{ name }}</template> |
| 46 | + <template v-slot:three="{ name }">Hello {{name }}</template> |
| 47 | +</TestComponent> |
| 48 | +``` |
| 49 | + |
| 50 | +Here `v-slot` is repeated multiple times where the actual differing part is the slot name (denoted by the argument). |
| 51 | + |
| 52 | +The shorthand helps slot names to be more easily scan-able: |
| 53 | + |
| 54 | +``` html |
| 55 | +<TestComponent> |
| 56 | + <template #one="{ name }">Hello {{ name }}</template> |
| 57 | + <template #two="{ name }">Hello {{ name }}</template> |
| 58 | + <template #three="{ name }">Hello {{name }}</template> |
| 59 | +</TestComponent> |
| 60 | +``` |
| 61 | + |
| 62 | +# Detailed design |
| 63 | + |
| 64 | +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 (`#`). |
| 65 | + |
| 66 | +``` html |
| 67 | +<!-- full syntax --> |
| 68 | +<foo> |
| 69 | + <template v-slot:header="{ msg }"> |
| 70 | + Message from header: {{ msg }} |
| 71 | + </template> |
| 72 | + |
| 73 | + <template v-slot:footer> |
| 74 | + A static footer |
| 75 | + </template> |
| 76 | +</foo> |
| 77 | + |
| 78 | +<!-- shorthand --> |
| 79 | +<foo> |
| 80 | + <template #header="{ msg }"> |
| 81 | + Message from header: {{ msg }} |
| 82 | + </template> |
| 83 | + |
| 84 | + <template #footer> |
| 85 | + A static footer |
| 86 | + </template> |
| 87 | +</foo> |
| 88 | +``` |
| 89 | + |
| 90 | +**Similar to `v-bind` and `v-on`, the shorthand only works when an argument is present. This means `v-slot` without an argument cannot be simplified to `#=`.** For default slots, either the full syntax (`v-slot`) or an explicit name (`#default`) should be used. |
| 91 | + |
| 92 | +``` html |
| 93 | +<foo v-slot="{ msg }"> |
| 94 | + {{ msg }} |
| 95 | +</foo> |
| 96 | + |
| 97 | +<foo #default="{ msg }"> |
| 98 | + {{ msg }} |
| 99 | +</foo> |
| 100 | +``` |
| 101 | + |
| 102 | +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. |
| 103 | + |
| 104 | +Some example usage in a real-world library that relies on scoped slots ([vue-promised](https://github.com/posva/vue-promised)): |
| 105 | + |
| 106 | + ``` html |
| 107 | +<Promised :promise="usersPromise"> |
| 108 | + <template #pending> |
| 109 | + <p>Loading...</p> |
| 110 | + </template> |
| 111 | + |
| 112 | + <template #default="users"> |
| 113 | + <ul> |
| 114 | + <li v-for="user in users">{{ user.name }}</li> |
| 115 | + </ul> |
| 116 | + </template> |
| 117 | + |
| 118 | + <template #rejected="error"> |
| 119 | + <p>Error: {{ error.message }}</p> |
| 120 | + </template> |
| 121 | +</Promised> |
| 122 | +``` |
| 123 | + |
| 124 | +# Drawbacks |
| 125 | + |
| 126 | +- 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: |
| 127 | + |
| 128 | + 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). |
| 129 | + |
| 130 | + 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. |
| 131 | + |
| 132 | +# Alternatives |
| 133 | + |
| 134 | +Some alternative symbols have been presented and discussed in the previous RFC. The only other one with similarly positive interest is `&`: |
| 135 | + |
| 136 | +``` html |
| 137 | +<foo> |
| 138 | + <template &header="{ msg }"> |
| 139 | + Message from header: {{ msg }} |
| 140 | + </template> |
| 141 | + |
| 142 | + <template &footer> |
| 143 | + A static footer |
| 144 | + </template> |
| 145 | +</foo> |
| 146 | +``` |
| 147 | + |
| 148 | +# Adoption strategy |
| 149 | + |
| 150 | +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. |
| 151 | + |
| 152 | +# Unresolved questions |
| 153 | + |
| 154 | +N/A |
0 commit comments