You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js子组件Props数组排序报错问题及实现需求

Fixing Your Vue.js Sorting Issue

Let's walk through fixing your sorting problem—there are a handful of small issues in your code that are causing the error and preventing proper sorting:

1. You're Trying to Directly Modify Props (Plus a Typo!)

First, this.job.application has a typo—it should be this.job.applications (missing an 's'). Even bigger issue: Vue doesn't allow direct modification of props (they follow one-way data flow from parent to child). Changing props directly will throw errors and break reactivity. Instead, we'll use a computed property to handle sorting without touching the original prop data.

2. Incorrect Property Access

Your sort callback uses a.sortBy—this tries to access a property named sortBy on your application objects, not the dynamic sortBy variable you're passing. You need to use bracket notation: a[sortBy] to access the property matching your sort key.

3. String Sorting Doesn't Work with -

Since you're sorting by name (a string), using a[sortBy] - b[sortBy] will result in NaN (you can't subtract strings). Use localeCompare() for proper string sorting instead.

4. You're Not Handling Sort Direction

Your changeSort method doesn't actually respect the sortDirection parameter—it just runs a single sort direction. We need to flip the comparison result based on whether we want ascending or descending order.


Corrected Code

Here's the updated component with fixes applied:

Template Changes

Update the table body to use our sorted computed property, and fix the header arrow display to show an unsorted icon when not active:

<template>
  <div class="modal-backdrop">
    <div class="modal">
      <header class="modal-header">
        <slot name="header">
          <h3>{{job.name}}</h3>
          <button v-if="application.name" type="button" class="btn-close" @click="back">
            <i class="fa fa-arrow-left"></i> Back
          </button>
          <button type="button" class="btn-close" @click="close"> x </button>
        </slot>
      </header>
      <section class="modal-body">
        <div class="row">
          <div v-if="!application.name" class=" col-12 applications-list">
            <table class="table table-bordered">
              <thead>
                <tr>
                  <th>Name &nbsp; 
                    <i @click="changeSort('name', 'desc')" v-if="sortBy === 'name' && sortDirection === 'asc'" class="fa fa-sort-up"></i>
                    <i @click="changeSort('name', 'asc')" v-if="sortBy === 'name' && sortDirection === 'desc'" class="fa fa-sort-down"></i>
                    <i v-else class="fa fa-unsorted"></i>
                  </th>
                  <th>Email &nbsp;<i class="fa fa-unsorted"></i></th>
                  <th>Date &nbsp;<i class="fa fa-unsorted"></i></th>
                </tr>
              </thead>
              <tbody>
                <!-- Use the sorted computed property here -->
                <tr class="application-row" v-for="application in sortedApplications" :key="application.id" :application="application" @click="getApplication(application)">
                  <td>{{application.name}}</td>
                  <td>{{application.email}}</td>
                  <td>Applied {{moment(application.created_at).fromNow()}}</td>
                </tr>
              </tbody>
            </table>
          </div>
          <!-- Rest of your template remains the same -->
          <div v-if="application.name" class="col-12 applicant">
            <small>Applied {{moment(application.created_at).fromNow()}}</small>
            <h4 v-if="application.name">Name</h4><p>{{application.name}}</p>
            <h4 v-if="application.email">Email</h4><p>{{application.email}}</p>
            <h4 v-if="application.phone">Phone</h4><p>{{application.phone}}</p>
            <h4 v-if="application.linkedin">Linkedin</h4><p>{{application.linkedin}}</p>
            <h4 v-if="application.cover_letter">Coverletter</h4><p v-html="application.cover_letter"></p>
          </div>
        </div>
      </section>
      <footer class="modal-footer">
      </footer>
    </div>
  </div>
</template>

Script Changes

Add a computed property for sorted applications, and simplify the changeSort method to just update our sort state:

<script>
import moment from 'moment';
export default {
  name: 'ApplicationsList',
  props:['job'],
  data(){
    return{
      application: {name:'', email: '', created_at:'', phone: '', linkedin: '', cover_letter: ''},
      sortBy:'name',
      sortDirection:'asc',
    }
  },
  computed: {
    sortedApplications() {
      // Create a copy of the original array to avoid modifying the prop
      const applications = [...this.job.applications];
      
      return applications.sort((a, b) => {
        const valueA = a[this.sortBy];
        const valueB = b[this.sortBy];
        
        // Handle string sorting (like name/email)
        if (typeof valueA === 'string') {
          const compareResult = valueA.localeCompare(valueB);
          // Reverse result if descending
          return this.sortDirection === 'asc' ? compareResult : -compareResult;
        }
        
        // Handle number/date sorting (if needed later)
        return this.sortDirection === 'asc' ? valueA - valueB : valueB - valueA;
      });
    }
  },
  methods:{
    moment,
    close(){
      this.$emit('closeApplicationsRequest');
    },
    getApplication(application){
      this.application = application;
    },
    back(){
      this.application = '';
    },
    changeSort(sortBy, sortDirection){
      // Just update our sort state—computed property will handle the rest
      this.sortBy = sortBy;
      this.sortDirection = sortDirection;
    }
  },
}
</script>

Key Improvements Explained

  • Computed Property: sortedApplications is reactive—any change to sortBy, sortDirection, or the original job.applications prop will automatically re-sort the list.
  • No Prop Modification: We create a copy of the applications array with [...this.job.applications] so we never mutate the original prop data.
  • Proper Sorting Logic: Uses localeCompare() for strings and handles ascending/descending direction correctly.
  • Cleaner State Management: The changeSort method just updates our sort variables instead of trying to sort directly, keeping logic separated.

内容的提问来源于stack exchange,提问作者Luiz Wynne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:11:30