I have a component inside a .vue file that can benefit from reusing a chunk of code. I know I can move that code to a separate .vue file and import it as a new component. However, this component would not be used anywhere else and I'd like to avoid cluttering the directory. Is it possible to declare this component's template inside the parent without using the in-code template:"<div>.....</div>"
stuff?
This is the idea:
<template>
<div>
...some html here...
<div v-for="item in items">
{{item.name}}:
<div v-if="item.available">YES!</div>
<div v-else>NO :(</div>
</div>
...some other components and data here...
<div v-for="item in items">
{{item.name}}:
<div v-if="item.available">YES!</div>
<div v-else>NO :(</div>
</div>
</div>
</template>
I would like to be able to do something like this:
<template>
<div>
...some html here...
<div v-for="item in items">
<itemizer inline-template v-model="item">
{{value.name}}:
<div v-if="value.available">YES!</div>
<div v-else>NO :(</div>
</itemizer>
</div>
...some other components and data here...
<div v-for="item in items">
<itemizer v-model="item"/>
</div>
</div>
</template>
However, from what I understand this is not possible.
Vue allows only a single element as a template root. If multiple root elements are specified, unintended behaviors occur as follows: For single-file component with a . vue extension, Vue throws a compile error.
Vue Single-File Components (a.k.a. *.vue files, abbreviated as SFC) is a special file format that allows us to encapsulate the template, logic, and styling of a Vue component in a single file. Here's an example SFC: vue <script> export default { data() { return { greeting: 'Hello World!'
Using Props To Share Data From Parent To Child # VueJS props are the simplest way to share data between components. Props are custom attributes that we can give to a component. Then, in our template, we can give those attributes values and — BAM — we're passing data from a parent to a child component!
Single File Components(SFCs) are a style of application organization used by JavaScript UI libraries where each file represents a single component in all aspects. Typically they resemble an HTML document where you have HTML tags, Style Tag, and Script Tag all in a file.
Unfortunately this pattern does not appear to be supported by the creator of Vue:
I personally feel the syntax is less maintainable than [Single File Components]
Note that we want to keep the SFC syntax as consistent possible, because it involves a big ecosystem of tools that need to support any new features added (e.g. Vetur would need to do something very different for handling SFCs with multiple scripts/templates). The proposed syntax, IMO, does not justify adding the new syntax.
https://github.com/vuejs/vue/pull/7264#issuecomment-352452213
That's too bad, as even beyond flexibility and developer choice, there is a good argument for inlining small functions that are not used by other components in order to reduce complexity. It's a common pattern in React and does not inhibit Single File Components when they're needed. In fact it allows gradual migration as inline components grow.
Here's one of the only resources currently that offers some potential workarounds: https://codewithhugo.com/writing-multiple-vue-components-in-a-single-file/
I've tried them all and am not satisfied with any of them at this time. At best you can set runtimerCompiler: true
and use template strings, but it'll add 10KB to your bundle and you'll likely miss out on full syntax highlighting available in the <template>
element. Maybe you can hack Teleport, but I have not made a dedicated attempt.
Actually, this should work. Just register your Vue inline-template like this in the section of your parent .vue file:
<template>
<div v-for="item in items">
<test-template :item="item">
<h1>{{item.text}}</h1>
</test-template>
</div>
</template>
<script>
Vue.component('test-template', {
template:'#hello-world-template',
props: {
item: Object
}
});
export default {...}
</script>
In your parent HTML file, put this:
<script type="text/x-template" id="hello-world-template">
<p>Hello hello hello</p>
</script>
With vue3 there are multiple options:
const Named = defineComponent(() => {
const count = ref(0)
const inc = () => count.value++
return () => (
<button class="named" onClick={inc}>
named {count.value}
</button>
)
})
There is another option described by Michael Thiessen here
Also you can have multiple render function components in one file: https://staging.vuejs.org/guide/extras/render-function.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With