【问题标题】:Component template should contain exactly one root element nuxt组件模板应该只包含一个根元素 nuxt
【发布时间】:2019-03-22 17:50:09
【问题描述】:

我不确定这可能是什么问题,但我正在使用 nuxt 制作 SPA 应用程序。我从 codepen 获得的一段已经编译的代码中出现错误。链接到codepen

https://codepen.io/jjelic/pen/yevNLZ?editors=1010

当我在我的 nuxt 应用程序中尝试此代码时,出现错误。 我在 pages 文件夹中添加了一个名为 monitor.vue 的文件,并像这样添加了 html 和 js

这种根元素错误是否常见,因为我以前在 html 中从未遇到过它,我该如何避免?

Vue.filter('currencyDisplay', {
  // model -> view
  read: function(val) {
    if (val > 0) {
      return accounting.formatMoney(val, "$", 2, ".", ",");
    }
  },
  // view -> model
  write: function(val, oldVal) {
    return accounting.unformat(val, ",");
  }
});

Vue.directive('sortable', {
  twoWay: true,
  deep: true,
  bind: function() {
    var that = this;

    var options = {
      draggable: Object.keys(this.modifiers)[0]
    };

    this.sortable = Sortable.create(this.el, options);
    console.log('sortable bound!')

    this.sortable.option("onUpdate", function(e) {
      that.value.splice(e.newIndex, 0, that.value.splice(e.oldIndex, 1)[0]);
    });

    this.onUpdate = function(value) {
      that.value = value;
    }
  },
  update: function(value) {
    this.onUpdate(value);
  }
});

var vm = new Vue({
  el: '#app',
  data: {
    rows: [
      //initial data
      {
        qty: 5,
        description: "Something",
        price: 55.20,
        tax: 10
      },
      {
        qty: 2,
        description: "Something else",
        price: 1255.20,
        tax: 20
      },
    ],
    total: 0,
    grandtotal: 0,
    taxtotal: 0,
    delivery: 40
  },
  computed: {
    total: function() {
      var t = 0;
      $.each(this.rows, function(i, e) {
        t += accounting.unformat(e.total, ",");
      });
      return t;
    },
    taxtotal: function() {
      var tt = 0;
      $.each(this.rows, function(i, e) {
        tt += accounting.unformat(e.tax_amount, ",");
      });
      return tt;
    }
  },
  methods: {
    addRow: function(index) {
      try {
        this.rows.splice(index + 1, 0, {});
      } catch (e) {
        console.log(e);
      }
    },
    removeRow: function(index) {
      this.rows.splice(index, 1);
    },
    getData: function() {
      $.ajax({
        context: this,
        type: "POST",
        data: {
          rows: this.rows,
          total: this.total,
          delivery: this.delivery,
          taxtotal: this.taxtotal,
          grandtotal: this.grandtotal,
        },
        url: "/api/data"
      });
    }
  }
});
<template>
  <div class="panel-body" id="app">
    <table class="table table-hover">
      <thead>
        <tr>
          <th style="width: 20px;">No.</th>
          <th>Description</th>
          <th style="width: 80px;">Qty</th>
          <th style="width: 130px;" class="text-right">Price</th>
          <th style="width: 90px;">Tax</th>
          <th style="width: 130px;">Total</th>
          <th style="width: 130px;"></th>
        </tr>
      </thead>
      <tbody v-sortable.tr="rows">
        <tr v-for="row in rows" track-by="$index">
          <td>
            {{ $index +1 }}
          </td>
          <td>
            <input class="form-control" v-model="row.description" />
          </td>
          <td>
            <input class="form-control" v-model="row.qty" number />
          </td>
          <td>
            <input class="form-control text-right" v-model="row.price | currencyDisplay" number data-type="currency" />
          </td>
          <td>
            <select class="form-control" v-model="row.tax">
              <option value="0">0%</option>
              <option value="10">10%</option>
              <option value="20">20%</option>
            </select>
          </td>
          <td>
            <input class="form-control text-right" :value="row.qty * row.price | currencyDisplay" v-model="row.total | currencyDisplay"
              number readonly />
            <input type="hidden" :value="row.qty * row.price * row.tax / 100" v-model="row.tax_amount | currencyDisplay"
              number />
          </td>
          <td>
            <button class="btn btn-primary btn-xs" @click="addRow($index)">add row</button>
            <button class="btn btn-danger btn-xs" @click="removeRow($index)">remove row</button>
          </td>
        </tr>
      </tbody>
      <tfoot>

        <tr>
          <td colspan="5" class="text-right">TAX</td>
          <td colspan="1" class="text-right">{{ taxtotal | currencyDisplay }}</td>
          <td></td>
        </tr>
        <tr>
          <td colspan="5" class="text-right">TOTAL</td>
          <td colspan="1" class="text-right">{{ total | currencyDisplay }}</td>
          <td></td>
        </tr>
        <tr>
          <td colspan="5" class="text-right">DELIVERY</td>
          <td colspan="1" class="text-right"><input class="form-control text-right" v-model="delivery | currencyDisplay"
              number /></td>
          <td></td>
        </tr>
        <tr>
          <td colspan="5" class="text-right"><strong>GRANDTOTAL</strong></td>
          <td colspan="1" class="text-right"><strong>{{ grandtotal = total + delivery | currencyDisplay }}</strong></td>
          <td></td>
        </tr>
      </tfoot>
    </table>
    <button @click="getData()">SUBMIT DATA</button>
    <pre>{{ $data | json }}</pre>
  </div>
</template>

【问题讨论】:

  • 您的 HTML sn-p 似乎是一个组件,但您的脚本创建了一个绑定到 #app 元素的新 Vue 实例。这似乎不对

标签: javascript vue.js vuejs2 nuxt.js


【解决方案1】:

这个问题其实是一个很简单的问题。我不知道 vue,但是 render 方法和 react 有相同的限制:每个组件必须在其模板中只有一个根元素。

这意味着不接受这样的情况:

<template>
  <div></div>
  <div></div>
</template>

但这样是正确的:

<template>
  <div></div>
</template>

这当然意味着,在你没有向我们展示的代码中,你将两个元素作为模板的根

【讨论】:

  • @Phil 是的,正是出于这个原因,我写了“不知何故在你没有向我们展示的代码中”,因为我坚信他正在运行的代码中有两个根元素,因为从他发布的代码中,如果你问我,它没有理由给出这个错误:)
  • 我在另一个文件中删除了一个 hello world 测试,该文件被定向到另一个导致相同问题的 url。这个根元素错误已经过去了。上面的代码有一个新错误` - :value="row.qty * row.price | currencyDisplay" 与同一元素上的 v-model 冲突,因为后者已经在内部扩展为值绑定`这可能是由于用 nuxt 选择单页应用?
  • @GiacomoCerquone 我出去了,这个就是你的了
  • @tomoc4 请,我知道现在很难在 stackoverflow 中得到答案,但是在 cmets 中询问更多是无法管理的。由于您的代码引发了一个新错误,请问您是否可以打开一个新问题并将其标记为已解决。另外我不知道 vue,我是 angular/react 开发者 :)
  • @Giaomo Cerquone 注意。感谢您让我知道导致错误的原因。我将标记为已解决。谢谢
猜你喜欢
  • 2017-09-20
  • 2017-12-13
  • 2020-05-28
  • 2018-02-10
  • 2017-03-18
  • 2018-04-23
  • 2015-06-05
  • 2019-07-07
  • 2021-10-01
相关资源
最近更新 更多