When dealing with Vue, the most reliable source of information can be found in the official documentation.
Theory:
The template plays a crucial role in each Vue component. Without a template (or a render
function, which essentially serves as a template), a Vue component will not render properly.
Templates can be provided in various ways:
I will skip discussing render functions as they may not be relevant for your current situation. Vue has the ability to parse both HTML and JSX. Additionally, Vue loader supports pre-processors, making it compatible with PUG by using a plugin.
Practice:
Register the templates as components, assigning the desired template
attribute along with any accompanying elements such as props
, data
, computed
, methods
, components
, directives
, filters
, emits
, watch
, expose
, compilerOptions
, inheritAttrs
, mixins
, extends
, and/or lifecycle hooks.
Integrate these components into your application.
Demo 3:
Vue.component('some-list', {
template: '#some-list',
props: ['powers']
})
Vue.component('some-item', {
template: '#some-item',
props: ['value']
})
Vue.component('svg-example', {
template: '#svg-example'
})
new Vue({
el: '#app',
data: () => ({
myComponents: ['some-list', 'svg-example'],
powers: 8
}),
methods: {
getPowers(comp) {
return (comp === 'some-list') && Number(this.powers)
}
}
})
#app {
display: flex;
justify-content: space-evenly;
}
#app input {
height: min-content;
}
#app div > div {
padding: 3px 7px;
}
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1c6a69795c2e322a322d28">[email protected]</a>/dist/vue.min.js"></script>
<div id="app">
<span v-text="powers"></span>
<input type="range" v-model="powers" min="2" max="12">
<component v-for="component in myComponents"
:powers="getPowers(component)"
:key="component"
:is="component" />
</div>
<template id="some-list">
<div>
<some-item v-for="(item, key) in powers" :key="key" :value="item" />
</div>
</template>
<template id="some-item">
<div v-text="Math.pow(2, value)" />
</template>
<template id="svg-example">
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 300 200"
width="300">
<image href="https://picsum.photos/300/200" />
</svg>
</template>
Same example 4, 5, but registering the components locally within the app instead of globally in Vue:
new Vue({
el: '#app',
components: {
SomeList: {
template: '#some-list',
props: ['powers'],
components: {
SomeItem: {
template: '<div v-text="Math.pow(2, value)" />',
props: ['value']
}
}
},
SvgExample: {
template: '#svg-example'
}
},
data: () => ({
powers: 8
})
})
#app {
display: flex;
justify-content: space-evenly;
}
#app input {
height: min-content;
}
#app div > div {
padding: 3px 7px;
}
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="99efecfcd9abb7afb7a8ad">[email protected]</a>/dist/vue.min.js"></script>
<div id="app">
<span>{{powers}}</span>
<input type="range" v-model="powers" min="2" max="12">
<some-list :powers="Number(powers)"></some-list>
<svg-example></svg-example>
</div>
<script type="text/x-template" id="some-list">
<div>
<some-item v-for="(item, key) in powers" :key="key" :value="item" />
</div>
</script>
<!-- innerHTML of this hidden div is used as template -->
<div id="svg-example" style="display: none">
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 300 200"
width="300">
<image href="https://picsum.photos/id/4/300/200" />
</svg>
</div>
Notes:
1 - Only effective inside new Vue({})
.
2 - The placeholder (initial DOM element) gets replaced during Vue's mounting process, causing any prior event registrations on the element to be lost.
3 - Templates can exist anywhere in the DOM, not restricted to being inside the Vue app itself.
4 - More rigid (SomeItem
component must be declared within SomeList
component, otherwise <SomeList />
cannot utilize it - somewhat unexpected behavior).
5 - I made some tweaks between the two examples with alternate syntaxes for comparison purposes.