Skip to content

Commit 9f17365

Browse files
authored
Remove inline-template (#98)
* remove inline-template * Update 0000-remove-inline-templates.md * Update 0000-remove-inline-templates.md * Rename 0000-remove-inline-templates.md to 0016-remove-inline-templates.md
1 parent ef55401 commit 9f17365

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
- Start Date: 2019-11-14
2+
- Target Major Version: 3.x
3+
- Reference Issues: N/A
4+
- Implementation PR: (leave this empty)
5+
6+
# Summary
7+
8+
Remove support for the [inline-template feature](https://vuejs.org/v2/guide/components-edge-cases.html#Inline-Templates).
9+
10+
# Motivation
11+
12+
`inline-template` was originally included in Vue to address the cases where Vue is used to progressively enhance a traditionally server-rendered application (e.g. with Rails, Django or Laravel). It allows users to define the template of a child component directly inside a parent's template.
13+
14+
The biggest issue with `inline-template` is that it makes template scoping very inconsistent. Without `inline-template`, a simple rule of thumb is that every variable appearing inside a template is either provided by the owner component, or by a directive that explicitly introduces scope variables (e.g. `v-for` and `v-slot`). `inline-template` breaks that assumption by mixing multiple scoping contexts in the same template:
15+
16+
``` html
17+
<div>
18+
{{ parentMsg }}
19+
<child-comp inline-template>
20+
{{ parentMsg }}
21+
</child-comp>
22+
</div>
23+
```
24+
25+
In a standard component expecting slots, `{{ parentMsg }}` would work intuitively inside the slot content. However with `inline-template`, that is no longer the case. Similarly components with `v-for` + `inline-template` won't work as expected either:
26+
27+
``` html
28+
<child-comp inline-template v-for="item in list">
29+
{{ item.msg }}
30+
</child-comp>
31+
```
32+
33+
Here the inner template actually has no access to the iterated `item`. It's pointing to `this.item` on the child component instead.
34+
35+
# Adoption strategy
36+
37+
## Replacement 1: `<script>` tag
38+
39+
Most of the use cases for `inline-template` assumes a no-build-tool setup, where all templates are written directly inside the HTML page. The most straightforward workaround in such cases is using `<script>` with an alternative type:
40+
41+
``` html
42+
<script type="text/html" id="my-comp-template">
43+
<div>
44+
{{ hello }}
45+
</div>
46+
</script>
47+
```
48+
49+
And in the component, target the template using a selector:
50+
51+
``` js
52+
const MyComp = {
53+
template: '#my-comp-template',
54+
// ...
55+
}
56+
```
57+
58+
This doesn't require any build setup, works in all browsers, is not subject to in-DOM HTML parsing caveats (e.g. you can use camelCase prop names), and provides proper syntax highlighting in most IDEs. In a traditional server-side framework, these templates can be split out into server template partials (included into the main HTML template) for better maintainability.
59+
60+
## Replacement 2: Default Slot
61+
62+
A component previously using `inline-template` can be refactored into using the default slot - which makes the data scoping more explicit while preserving the convenience of writing child content inline:
63+
64+
``` html
65+
<!-- before -->
66+
<my-comp inline-template :msg="parentMsg">
67+
{{ msg }} {{ childState }}
68+
</my-comp>
69+
70+
<!-- after -->
71+
<my-comp v-slot="{ childState }">
72+
{{ parentMsg }} {{ childState }}
73+
</my-comp>
74+
```
75+
76+
The child, instead of providing no template, should now render the default slot (Note in v3 due to fragment support you can render a slot as the root now):
77+
78+
``` html
79+
<!--
80+
in child template, render default slot while passing
81+
in necessary private state of child.
82+
-->
83+
<slot :childState="childState" />
84+
```

0 commit comments

Comments
 (0)