I have a Vue ponent inside a Vue loop on my website. Here's the JS file:
Vueponent('fb-question-text', {
props: ['question'],
template:
'<label>Prompt</label><input type="text" class="form-control" v-model="question.prompt"><a href="javascript:void" class="fb-remove">Remove</a>'
});
var questionList = new Vue({
el: '#questions',
data: {
questions: [
{
type: 'text',
id: 'question1',
prompt: ''
},
{
type: 'choice',
id: 'question2',
prompt: '',
choices: ['', '']
}
]
}
});
This is what my HTML file looks like:
<ul id="questions">
<li v-for="(question, index) in questions">
<h4>Question {{ index + 1 }}</h4>
<fb-question-text v-if="question.type === 'text'" :question="question"></fb-question-text>
</li>
</ul>
As you can see, I am trying to render the fb-question-text ponent if the question.type is of type "text". While the <li>
elements do render in the page, the ponent template does not render entirely. Only the first DOM element inside the template is rendered (in this case, the <label>
element). The input box and <a>
that are inside the ponent do not get rendered for some reason. When I remove the label, the input box gets rendered but nothing after it.
Can someone tell me what is going on?
I have a Vue ponent inside a Vue loop on my website. Here's the JS file:
Vue.ponent('fb-question-text', {
props: ['question'],
template:
'<label>Prompt</label><input type="text" class="form-control" v-model="question.prompt"><a href="javascript:void" class="fb-remove">Remove</a>'
});
var questionList = new Vue({
el: '#questions',
data: {
questions: [
{
type: 'text',
id: 'question1',
prompt: ''
},
{
type: 'choice',
id: 'question2',
prompt: '',
choices: ['', '']
}
]
}
});
This is what my HTML file looks like:
<ul id="questions">
<li v-for="(question, index) in questions">
<h4>Question {{ index + 1 }}</h4>
<fb-question-text v-if="question.type === 'text'" :question="question"></fb-question-text>
</li>
</ul>
As you can see, I am trying to render the fb-question-text ponent if the question.type is of type "text". While the <li>
elements do render in the page, the ponent template does not render entirely. Only the first DOM element inside the template is rendered (in this case, the <label>
element). The input box and <a>
that are inside the ponent do not get rendered for some reason. When I remove the label, the input box gets rendered but nothing after it.
Can someone tell me what is going on?
Share Improve this question edited Dec 16, 2017 at 17:32 Abdennour TOUMI 93.8k42 gold badges268 silver badges269 bronze badges asked Dec 16, 2017 at 17:20 JackHJackH 4,7454 gold badges38 silver badges64 bronze badges4 Answers
Reset to default 8Templates must have a single root element.
<span>
<label>Prompt</label>
<input type="text" class="form-control" v-model="question.prompt">
<a href="javascript:void" class="fb-remove">Remove</a>
</span>
Your fb-question-text
is only allowed to have one root element. You need to wrap that in a div.
Add <div>
around template
html
Vue.ponent('fb-question-text', {
props: ['question'],
template: '<div><label>Prompt</label><input type="text" class="form-control" v-model="question.prompt"><a href="javascript:void" class="fb-remove">Remove</a></div>'
});
var questionList = new Vue({
el: '#questions',
data: {
questions: [
{
type: 'text',
id: 'question1',
prompt: ''
},
{
type: 'choice',
id: 'question2',
prompt: '',
choices: [ '' , '' ]
}
]
}
});
<script src="https://cdnjs.cloudflare./ajax/libs/vue/2.5.11/vue.js"></script>
<ul id="questions">
<li v-for="(question, index) in questions">
<h4>Question {{ index + 1 }}</h4>
<fb-question-text v-if="question.type === 'text'" :question="question"></fb-question-text>
</li>
</ul>
For a similar question I purpose an other answer : Vue js error: Component template should contain exactly one root element
copy paste here :
if, for any reasons, you don't want to add a wrapper (in my first case it was for <tr/>
ponents), you can use a functionnal ponent.
Instead of having a single ponents/MyCompo.vue
you will have few files in a ponents/MyCompo
folder :
ponents/MyCompo/index.js
ponents/MyCompo/File.vue
ponents/MyCompo/Avatar.vue
With this structure, the way you call your ponent won't change.
ponents/MyCompo/index.js
file content :
import File from './File';
import Avatar from './Avatar';
const monSort=(a,b)=>b-a;
export default {
functional: true,
name: 'MyCompo',
props: [ 'someProp', 'plopProp' ],
render(createElement, context) {
return [
createElement( File, { props: Object.assign({light: true, sort: monSort},context.props) } ),
createElement( Avatar, { props: Object.assign({light: false, sort: monSort},context.props) } )
];
}
};
And if you have some function or data used in both templates, passed them as properties and that's it !
I let you imagine building list of ponents and so much features with this pattern.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744791179a4593923.html
评论列表(0条)