【问题标题】:Vue component renders only the first element in the template DOMVue 组件只渲染模板 DOM 中的第一个元素
【发布时间】:2018-05-30 14:22:57
【问题描述】:

我的网站上的 Vue 循环中有一个 Vue 组件。这是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: ['', '']
      }
    ]
  }
});

这是我的 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>

如您所见,如果 question.type 的类型为“text”,我正在尝试渲染 fb-question-text 组件。虽然&lt;li&gt; 元素确实在页面中呈现,但组件模板并未完全呈现。仅呈现模板内的第一个 DOM 元素(在本例中为 &lt;label&gt; 元素)。由于某种原因,组件内部的输入框和&lt;a&gt; 未呈现。当我删除标签时,输入框会被渲染,但之后什么都没有。

谁能告诉我这是怎么回事?

【问题讨论】:

    标签: javascript vue.js


    【解决方案1】:

    对于类似的问题,我打算提供另一个答案: Vue js error: Component template should contain exactly one root element

    复制粘贴到这里:

    如果出于任何原因,您不想添加包装器(在我的第一种情况下,它是为&lt;tr/&gt; 组件),您可以使用函数式组件。

    components/MyCompo 文件夹中的文件很少:

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

    使用这种结构,您调用组件的方式不会改变。

    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) } )
        ]; 
      }
    };
    

    如果您在两个模板中都使用了一些函数或数据,请将它们作为属性传递,就是这样!

    我让您想象使用这种模式构建组件列表和许多功能。

    【讨论】:

      【解决方案2】:

      template html 周围添加&lt;div&gt;

      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>

      【讨论】:

        【解决方案3】:

        您的fb-question-text 只允许有一个根元素。您需要将其包装在一个 div 中。

        【讨论】:

          【解决方案4】:

          模板必须有一个根元素。

          <span>
            <label>Prompt</label>
            <input type="text" class="form-control" v-model="question.prompt">
            <a href="javascript:void" class="fb-remove">Remove</a>
          </span>
          

          【讨论】:

            猜你喜欢
            • 2023-03-23
            • 1970-01-01
            • 1970-01-01
            • 2021-10-01
            • 2020-06-12
            • 2017-02-08
            • 2021-11-20
            • 2017-12-13
            • 2021-02-28
            相关资源
            最近更新 更多