为什么 sort 方法在父组件中不起作用?

Why the sort method not working in the parent component?

这是我在 VueJS 中的第一个项目。 我有一个产品列表,想按价格对其进行排序。我构建了两个组件并尝试通过发出事件将排序方法从子组件(下拉按钮)传递给父组件。但经过多次尝试,我找不到我的代码的错误,任何帮助!

此子组件:

<template>
  <div class="dropdown">
    <button
      @click="toggleShow(); $emit('sortPrice')"
      class="dropbtn"
    >
      {{ title }}
      <span class="material-icons-outlined"> {{ icon }} </span>
    </button>

    <div v-if="showMenu" class="menu">
      <div class="menu-item" v-for="(item, index) in this.items" :key="index">
        {{ item }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "Dropdown-menu",

  props: {
    title: String,
    icon: String,
    items: {
      type: Object,
      required: true,
    },
  },

  data() {
    return {
      showMenu: false
    };
  },

  methods: {
    toggleShow: function () {
      this.showMenu = !this.showMenu;
    },

    sortPrice: function () {
      this.$emit("sort", this.sortPrice);
    },
  },
};
</script>

这个父组件:

<template>
    <dropdown
          :title="sortedBy"
          :items="arrangements"
          :icon="material_icons"
          @sort="sortByPrice"
    ></dropdown>
</template>

<script>
import Dropdown from "@/components/Dropdown.vue";

export default {
  components: {
    Dropdown,
  },

  data() {
    return {
      sortedBy: "Featured",
      arrangements: ["Featured", "Lowest", "Highest"],
      material_icons: "expand_more",
      productData: require("@/data/store-data.json"),
    };
  },
  methods: {
    sortByPrice: function () {
      let realProducts = this.productData.products;
      let sortedProducts = realProducts.sort((a, b) => {
        if (this.sortedBy === "Highest") {
          return b.price - a.price;
        } else if (this.sortedBy === "Lowest") {
          return a.price - b.price;
        }
      });
      return sortedProducts;
    },
  },
};
</script>

建议:

  • 在单击 dividual 项目时发出,而不是在单击按钮时发出。你想在用户做出选择时发出
  • 所以这意味着通过 @click="sortPrice(item)"
  • 从 menu-item div 调用 sortPrice 函数
  • 然后在 sortPrice 函数中,传入项目参数 function (item) { 并将其作为第二个参数传递给您的 emit 调用:this.$emit("sort", item);。家长必须知道选择了什么
  • 在父组件sortByPrice函数中,接受item参数,sortByPrice: function (item) {并用它来设置sortedBy属性:this.sortedBy = item;
  • 在随后显示的计算 属性 中进行排序,在我的示例中称为 sortedProducts

例如,家长:

<template>
  <h2>Main App</h2>
  <dropdown
    :title="sortedBy"
    :items="arrangements"
    @sort="sortByPrice"
  ></dropdown>
  <div>
    <h3>Products</h3>
    <ul>
      <li v-for="product in sortedProducts" :key="product.index">
        {{ product.name }} ${{ product.price }}
      </li>
    </ul>
  </div>
</template>

<script>
import Dropdown from "@/components/Dropdown.vue"; 

export default {
  components: {
    Dropdown,
  },

  data() {
    return {
      sortedBy: "Featured",
      arrangements: ["Featured", "Lowest", "Highest"],
      productData: {
        // dummy data for demo purposes
        products: [
          { index: 1, name: "product A", price: 1, featured: true },
          { index: 2, name: "product B", price: 2, featured: false },
          { index: 3, name: "product C", price: 6, featured: true },
          { index: 4, name: "product G", price: 4, featured: false },
          { index: 5, name: "product V", price: 0, featured: true },
        ],
      },
    };
  },
  methods: {
    sortByPrice: function (item) {
      this.sortedBy = item;
    },
  },
  computed: {
    sortedProducts: function () {
      if (this.sortedBy === "Featured") {
        return this.productData.products.filter((prod) => prod.featured);
      } else if (this.sortedBy === "Highest") {
        return this.productData.products.sort((a, b) => b.price - a.price);
      } else if (this.sortedBy === "Lowest") {
        return this.productData.products.sort((a, b) => a.price - b.price);
      }
      // the "just-in-case" default return
      return this.productData.products;
    },
  },
};
</script>

和子 Dropdown.vue 组件:

<template>
  <div class="dropdown">
    <button @click="toggleShow()" class="dropbtn">
      {{ title }}
    </button>

    <div v-if="showMenu" class="menu">
      <div
        class="menu-item"
        v-for="(item, index) in this.items"
        :key="index"
        @click="sortPrice(item)"
      >
        {{ item }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "Dropdown-menu",

  props: {
    title: String,
    items: {
      type: Object,
      required: true,
    },
  },

  data() {
    return {
      showMenu: false,
    };
  },

  methods: {
    toggleShow: function () {
      this.showMenu = !this.showMenu;
    },

    sortPrice: function (item) {
      this.$emit("sort", item);
      this.toggleShow();
    },
  },
};
</script>