【问题标题】:Vue js event not picked upVue js事件未拾取
【发布时间】:2017-04-05 21:19:27
【问题描述】:

我刚刚开始尝试使用 vue js,并且正在使用它构建一个结帐表单。我也在为该项目使用Symfony 31。在结帐/注册页面上,我有一个嵌入的代表订单项目的表单集合(每个都是对一种产品的订阅)。您可以通过勾选复选框来选择多个项目。您也可以更改数量。不幸的是,我无法将数量更新传递给Vue 实例。条目在渲染时注册为数量 1,如果我更改数量然后选择项目,则价格计算正确,但应用程序将其注册为新实体。与数量的绑定不起作用。我还需要添加一个名为频率的类似字段,我知道我会遇到同样的问题。帮助?

这里是 js 小提琴:https://jsfiddle.net/wavsu8xm/

Javascript:

var bus = new Vue();

var entriesComponent = Vue.component('entries', {
  template: '#entries',
  props: {
    entries: [Array, Object],
    selected: Array,
    addons: Array,
    frequencies: [Array, Object],
  },
  watch: {
    selected: function(val, oldVal) {
      bus.$emit('selected-changed', val);
    },
  }
});

new Vue({
  el: '#app',
  data: {
    entries: [],
    selected: [],
    addons: [],
    frequencies: [],
    paymentConfig: {
      advance: 25,
      firstweek: 25,
      ondelivery: 50,
    },
    weeks: 12,
  },
  components: {
    'entriesComponent': entriesComponent,
  },
  created: function() {
    // store this to use with Vue.set
    var temp = this;
    bus.$on('selected-changed', function(selected) {
      // vm.$set deprecated
      Vue.set(temp, 'selected', selected);
    });
  },
  computed: {
    totalAdvance: function() {
      return (this.paymentConfig.advance * this.total) / 100;
    },
    totalFirstWeek: {
      get: function() {
        return (this.paymentConfig.firstweek * this.total) / 100;
      },
    },
    onDeliveryPayment: {
      get: function() {
        return (this.paymentConfig.ondelivery * this.total) / (this.weeks * 100);
      }
    },
    total: {
      get: function() {
        var sum = 0;
        var weeks = this.weeks;
        this.selected.forEach(function(item) {
          sum += weeks * item.itemPrice * item.quantity;
        });
        console.log(sum);
        return sum;
      }
    }
  }
});

模板:

<section class="content">
  <div class="row" id="app">
    <div class="col-md-8">
      <div class="box box-primary">
        <div class="box-body">
          <div class="row">
            <div class="col-md-12">
              <div class="form-group">
                <label class="control-label required">Items</label>
                <div class="col-md-12">
                  <entries :entries="{ 0 : { shareSize : 'Small', quantity : '1', itemPrice : '24', frequency : '' }, 1 : { shareSize : 'Medium', quantity : '1', itemPrice : '35', frequency : '' }, 2 : { shareSize : 'Large', quantity : '1', itemPrice : '46', frequency : '' } }"
                  :selected="selected"></entries>
                  <!-- component template -->
                  <template id="entries">
                    <div class="col-md-12">
                      <div class="form-group" v-for="(entry, key) in entries" v-bind:entry="entry">
                        <div class="form-group col-md-12">
                          <div class="col-md-12">
                            <div class="col-md-4">
                              <input type="checkbox" v-bind:value="entry" v-model="selected">
                            </div>
                            <div class="col-md-4">{{entry.shareSize}}</div>
                            <div class="col-md-4">{{'$ ' + Number(entry.itemPrice).toFixed(2) }}</div>
                          </div>
                          <div class="form-group col-md-12">
                            <div class="col-md-6">
                              <input type="number" v-model="entry.quantity" :value="entry.quantity" />
                            </div>
                          </div>

                        </div>
                      </div>
                    </div>
                  </template>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="col-md-4">
        <div class="box box-info">
          <div class="box-body" style="padding:15px;">
            <div class="container-fluid">
              <div class="form-group">
                <div class="control-label">
                  <label>Summary</label>
                </div>
                <div class="form-control" v-for="item in selected">
                  <span class="pull-left small-box-footer">{{ item.shareSize }}</span>
                  <span class="pull-right">{{ item.quantity + ' x $ ' + (item.itemPrice*item.quantity).toFixed(2)}}</span>
                </div>
                <div class="control-label">
                  <label>Payment plan</label>
                </div>
                <div class="col-md-12">
                  {{ '$ ' + totalAdvance.toFixed(2) }} - advance
                </div>
                <div class="col-md-12">
                  {{ '$ ' + totalFirstWeek.toFixed(2) }} - first week
                </div>
                <div class="col-md-12">
                  {{ '$ ' + onDeliveryPayment.toFixed(2) }}/ week on each of the {{ weeks }} weeks of the subscription
                </div>
                <div class="col-md-12 row">
                  <div class="control-label"><strong><span class="pull-left">Total</span><span class="pull-right">{{ '$ ' + total.toFixed(2) }}</span></strong></div>
                </div>
                <div class="col-md-12 row">
                  <div class="title"><strong><span class="pull-left">Total due now</span><span class="pull-right">{{ '$ ' + totalAdvance.toFixed(2) }}</span></strong></div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

【问题讨论】:

    标签: vue.js symfony vue-component


    【解决方案1】:

    你正在直接改变你的 props,当父组件重新渲染时,它会被覆盖,所以你需要在你的组件中复制它们,这可以在你组件的 created 方法中完成:

      created: function() {
        // copy props to data
        this.entriesCopy = this.entries;
        this.selectedCopy = this.selected;
      },
      data: function() {
        return{
         entriesCopy: [],
         selectedCopy: []
        }
      }
    

    现在你只需要更新你的观察者:

      watch: {
        selectedCopy: function(val, oldVal) {
          bus.$emit('selected-changed', val);
        }
      }
    

    还有你的模板:

    //...
    div class="form-group" v-for="(entry, key) in entriesCopy" v-bind:entry="entry">
    //...
    <input type="checkbox" v-bind:value="entry" v-model="selectedCopy">
    

    反映变化。

    这是更新后的 jsfiddle:https://jsfiddle.net/5pyw74h9/

    【讨论】:

    • 非常感谢!现在可以了!小更新: data(){ 应该写成 data: function() {
    • 是的,对不起,我使用Ecmascript 6 语法,需要通过babel 之类的东西编译才能在浏览器中使用,我将更新答案并改用Ecmascript 5
    • 我还有一个问题。我应该在这里添加还是新建一个?假设我想向页面添加两个 类型的元素(相同的组件),但我希望它们都写入同一个选定的数组。 (主视图中选中的属性应该是两个元素的并集)
    • @anegrea 您能否将其发布在一个新问题中,因为在这里很难回答。 :)
    猜你喜欢
    • 2022-10-18
    • 2019-01-07
    • 1970-01-01
    • 2019-05-24
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多