计算子组件的出现次数

时间:2018-04-26 16:12:15

标签: javascript vuejs2 vue-component

我有一个像这样的文件组件:

<template>
    <div>
        <template v-if="offers.length > 3">
            <a href="#">View all offers here</a>
        </template>

        <template v-else-if="offers.length > 1">
            <offer v-for="offer in offers" :data="offer"></offer>
        </template>

        <template v-else-if="offers.length == 1">
            <offer :title="The offer" :data="offers[0]"></offer>
        </template>
    </div>
</template>

根据offers的数量,我选择要渲染的数量。

问题:如何有效获取/计算<offer>组件的数量?我还需要这个号码来反应。

2 个答案:

答案 0 :(得分:1)

我的回答完全基于你想要计算Offer组件的实例化和破坏的想法。我不确定你为什么不算offers.length。也许其他事情可以触发实例化。

让组件在创建和销毁时发出事件,并相应地设置父轨道。

或者(也许是矫枉过正)你可以使用Vuex并创建一个Offer提交创建和销毁的商店。这意味着,每次在标记中添加@offer-created/destroyed时,您都不必手动附加<offer>指令。

以下示例中包含这两种方法:

&#13;
&#13;
const store = new Vuex.Store({
  strict: true,
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    },
    decrement(state) {
      state.count--;
    }
  }
});

const Offer = {
  props: ["data"],
  template: "<div>{{data.name}}</div>",
  created() {
    console.log("Created");
    this.$emit("offer-created");

    this.$store.commit("increment");
  },
  destroyed() {
    console.log("Destroyed");
    this.$emit("offer-destroyed");

    this.$store.commit("decrement");
  }
};

const app = new Vue({
  el: "#app",
  store,
  components: {
    offer: Offer
  },
  data() {
    return {
      offers: [],
      offerCount: 0
    };
  },
  computed: {
    offerCountFromStore() {
      return this.$store.state.count;
    }
  },
  methods: {
    offerCreated() {
      this.offerCount++;
    },
    offerDestroyed() {
      this.offerCount--;
    },
    addOffer() {
      this.offers.push({
        name: `Item: ${this.offers.length}`
      });
    },
    removeOffer() {
      this.offers.pop();
    }
  }
});
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
<div id="app">
  <div>Offer instances: {{offerCount}}</div>
  <div>Offer instances (from store): {{offerCountFromStore}}</div>
  <div>
    <div v-if="offers.length > 3">
      <a href="#">View all offers here</a>
    </div>
    <div v-else-if="offers.length > 1">
      <offer @offer-created="offerCreated" @offer-destroyed="offerDestroyed" v-for="offer in offers" :data="offer"></offer>
    </div>
    <div v-else-if="offers.length == 1">
      <offer @offer-created="offerCreated" @offer-destroyed="offerDestroyed" :data="offers[0]"></offer>
    </div>
  </div>
  <div>
    <button @click.prevent="addOffer">Add</button>
    <button @click.prevent="removeOffer">Remove</button>
  </div>
</div>
&#13;
&#13;
&#13;

尝试使用$children的问题在于,它本身并不是被动的:

  

当前实例的直接子组件。 注意没有   $children的订单保证,并且不是被动的。如果你找到了   您自己尝试使用$children进行数据绑定,请考虑使用   数组和v-for生成子组件,并使用数组作为   事实的来源。

答案 1 :(得分:1)

没有干净的方式。

您可以计算当前实例的特定类型的子项。但你必须打电话给&#34;重新计算&#34; update挂钩上的逻辑(以及mounted)。

示例:

&#13;
&#13;
Vue.component('offer', {
  name: 'Offer',
  template: '<span> offer </span>'
})
new Vue({
  el: '#app',
  data: {
    offers: [1, 2],
    offerCount: 0
  },
  methods: {
    updateOfferCount() {
      this.offerCount = this.$children.filter(child => child.constructor.options.name === 'Offer').length;
    }
  },
  updated() {
    this.updateOfferCount()
  },
  mounted() {
    this.updateOfferCount()
  }
})
&#13;
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <div>
    <template v-if="offers.length > 3">
        <a href="#">View all offers here</a>
    </template>

    <template v-else-if="offers.length > 1">
        <offer v-for="offer in offers" :data="offer"></offer>
    </template>

    <template v-else-if="offers.length == 1">
        <offer :data="offers[0]"></offer>
     </template>
  </div>
  <br>
  <button @click="offers.push(123)">Add Offer</button> offerCount: {{ offerCount }}
</div>
&#13;
&#13;
&#13;