【问题标题】:_.orderBy not sorting by column in Vue_.orderBy 不在 Vue 中按列排序
【发布时间】:2021-06-14 21:29:18
【问题描述】:

在 Vue2 中,当我在选择中选择一列时,我想按列对我的测验数组进行排序。但是当我更改选择时 _.orderBy (lodash) 不会排序,它会调整 sortDirection。 orderBy 在 sortDirection 更改时执行。我没有错误。有谁知道我做错了什么?非常感谢您的提示!

vue 组件

<template>
    <div class="py-6">
        <div class="max-w-7xl mx-auto lg:px-8">
            <div class="mt-5 flex lg:mt-0">
                <span class="block w-1/5">
                    <input v-model="search" autocomplete="no"
                           class="ml-3 border border-gray-300 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm rounded-md"
                           placeholder="Zoek hier naar quizzen..."
                           type="text">
                </span>

                <span class="block">
                    <select v-model="sortProperty"
                            class="ml-6 block w-full py-2 px-4 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
                            name="sortBy">
                        <option value="name">Naam</option>
                        <option value="playdate">Speeldatum</option>
                    </select>
                </span>

                <span class="block">
                    <button
                        class="ml-9 inline-flex justify-center py-2 border border-transparent text-sm font-medium rounded-md text-gray-500 focus:outline-none"
                        type="button" @click="sortDirection === 'asc' ? sortDirection = 'desc' : sortDirection = 'asc'">
                        <svg v-if="sortDirection === 'asc'" class="h-5 w-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"
                             xmlns="http://www.w3.org/2000/svg">
                            <path d="M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12" stroke-linecap="round"
                                  stroke-linejoin="round"
                                  stroke-width="2"/>
                        </svg>
                        <svg v-if="sortDirection === 'desc'" class="h-5 w-5 mr-3" fill="none" stroke="currentColor"
                             viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
                            <path d="M3 4h13M3 8h9m-9 4h9m5-4v12m0 0l-4-4m4 4l4-4" stroke-linecap="round"
                                  stroke-linejoin="round"
                                  stroke-width="2"/>
                        </svg>
                    </button>
                </span>
            </div>

            <div v-for="quiz in filteredQuizzes" v-if="filteredQuizzes.length > 0"
                 class="bg-white rounded-lg shadow-sm duration-500 px-2 sm:px-6 md:px-2 py-4 my-6">
                <div class="grid grid-cols-12 gap-3">
                    <div class="col-span-12 sm:col-start-3 sm:col-end-13 px-3 sm:px-0">
                        <div class="mt-2">
                            <a class="sm:text-sm md:text-md lg:text-lg text-gray-700 font-bold">
                                {{ quiz.name }}
                            </a>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import _ from 'lodash';
import axios from "axios";

export default {
    data() {
        return {
            search: '',

            sortProperty: 'name',
            sortDirection: 'asc',

            quizzes: [],
        }
    },

    computed: {
        filteredQuizzes() {
            let quizzes = this.quizzes.filter(quiz => quiz.name.toLowerCase().includes(this.search.toLowerCase()))

            return _.orderBy(quizzes, this.sortProperty, this.sortDirection)
        }
    },

    created() {
        this.fetchQuizzes();
    },

    methods: {
        fetchQuizzes() {
            axios.get('/quizzes').then(({data}) => (this.quizzes = data));
        },
    },

    name: "Quizzes"
}
</script>

【问题讨论】:

  • 我相信这应该可以正常工作。确保您在测验对象上有属性playdate(如果它们的值相同,则选择时不会看到任何变化)。也尽量不要在与v-for 相同的元素上使用v-if,并将:key 与v-for 一起使用。

标签: javascript vuejs2 lodash laravel-8 columnsorting


【解决方案1】:

编辑版

Vue.component("QuizItem", {
  props: ["name", "otherVar"],
  template: `
    <div>
      Name: {{ name }}<br>
      Other var: {{ otherVar }}<br>
      <hr />
    </div>
  `
})
new Vue({
  el: "#app",
  data() {
    return {
      search: "",
      sortDirection: "asc",
      sortProperty: "name",
      quizzes: [{
          name: "Quiz 34",
          otherVar: "DEF",
        },
        {
          name: "Quiz 23",
          otherVar: "GHI",
        },
        {
          name: "Quiz 12",
          otherVar: "JKL",
        },
        {
          name: "Quiz 45",
          otherVar: "ABC",
        },
      ]
    }
  },
  computed: {
    filteredQuizzes() {
      let quizzes = this.quizzes.filter(quiz => quiz.name
        .toLowerCase()
        .includes(
          this.search.toLowerCase()
        ))
      quizzes = _.orderBy(
        quizzes, [this.sortProperty], [this.sortDirection]
      )
      return quizzes
    },
  },
  template: `
    <div
      class="container"
    >
      <div class="quizzes col">
        <h4>FULL LIST:</h4>
        <quiz-item
          v-for="quiz in quizzes"
          :key="quiz.name"
          v-bind="quiz"
        />
      </div>
      <div class="quizzes col">
        <h4>FILTERED LIST:</h4>
        <quiz-item
          v-for="quiz in filteredQuizzes"
          :key="quiz.name"
          v-bind="quiz"
        />
      </div>
      <div class="filters col">
        <h4>CONTROLS</h4>
        <div>
          <span>Settings:</span>
          {{ search }}, {{ sortProperty }}, {{ sortDirection }}
        </div>
        <hr>
        <label>
          Search:
          <input type="text" v-model="search" />
        </label>
        <label>
          Sort property:
          <select v-model="sortProperty">
            <option value="name">Name</option>
            <option value="otherVar">Other var</option>
          </select>
        </label>
        <label>
          Sort direction:
          <select v-model="sortDirection">
            <option value="asc">ASC</option>
            <option value="desc">DESC</option>
          </select>
        </label>
      </div>
    </div>
  `
})
.container {
  display: flex;
}

.col {
  width: 33%;
  padding: 8px 16px;
}

label {
  display: block;
  padding-bottom: 8px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
<div id="app"></div>

试试上面的 sn-p - 它有效。问题出在这一行:

return _.orderBy(quizzes, this.sortProperty, this.sortDirection)

// this should be this:
return _.orderBy(quizzes, [this.sortProperty], [this.sortDirection])

原因是_.orderBy() 接受一个属性名称列表(数组),它将用来对数组进行排序以及另一个控制排序方向的列表(与属性名称的顺序相同)。这两个参数都应该是Arrays,即使你只设置了1个属性和1个对应的排序方向。

【讨论】:

  • 来自您发布的链接:Returns (Array): Returns the new sorted array.
  • @Beyers 你是对的,我只看了这个例子。但是你检查了吗?
  • @muka.gergely 感谢您的帮助,只是没有解决问题。事实上,使用 sortDirection 进行排序也不起作用。您还有其他建议吗?
  • @Beyers 编辑了我的答案(删除了不正确的部分并添加了一个有效的 sn-p)。我希望它仍然可以帮助你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-07
  • 1970-01-01
  • 2015-01-13
  • 2021-05-20
  • 1970-01-01
  • 2019-04-29
相关资源
最近更新 更多