简体   繁体   English

Vue组件仅呈现模板DOM中的第一个元素

[英]Vue component renders only the first element in the template DOM

I have a Vue component inside a Vue loop on my website. 我的网站上的Vue循环中有一个Vue组件。 Here's the JS file: 这是JS文件:

Vue.component('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: 这是我的HTML文件的样子:

<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 component if the question.type is of type "text". 正如您所看到的,如果question.type是“text”类型,我正在尝试呈现fb-question-text组件。 While the <li> elements do render in the page, the component template does not render entirely. <li>元素在页面中进行渲染时,组件模板不会完全呈现。 Only the first DOM element inside the template is rendered (in this case, the <label> element). 仅渲染模板内的第一个DOM元素(在本例中为<label>元素)。 The input box and <a> that are inside the component do not get rendered for some reason. 由于某种原因,组件内部的输入框和<a>不会被渲染。 When I remove the label, the input box gets rendered but nothing after it. 当我删除标签时,输入框会被渲染但后面没有任何内容。

Can someone tell me what is going on? 有人能告诉我发生了什么事吗?

Templates 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. 你的fb-question-text只允许有一个根元素。 You need to wrap that in a div. 你需要将它包装在一个div中。

Add <div> around template html template html周围添加<div>

 Vue.component('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.com/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 对于类似的问题,我提出了另一个答案: Vue js错误:组件模板应该只包含一个根元素

copy paste here : 复制粘贴在这里:

if, for any reasons, you don't want to add a wrapper (in my first case it was for <tr/> components), you can use a functionnal component. 如果出于任何原因,你不想添加包装器(在我的第一种情况下是<tr/>组件),你可以使用一个功能组件。

Instead of having a single components/MyCompo.vue you will have few files in a components/MyCompo folder : 您没有单个components/MyCompo.vue而是components/MyCompo文件夹中的文件很少:

  • components/MyCompo/index.js
  • components/MyCompo/File.vue
  • components/MyCompo/Avatar.vue

With this structure, the way you call your component won't change. 使用此结构,您调用组件的方式不会更改。

components/MyCompo/index.js file content : components/MyCompo/index.js文件内容:

import File from './File';
import Avatar from './Avatar';   

const commonSort=(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: commonSort},context.props) } ),
        createElement( Avatar, { props: Object.assign({light: false, sort: commonSort},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 components and so much features with this pattern. 我让你想象一下使用这种模式构建组件列表和很多功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM