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

Vue.js 2表格排序失效及指定列搜索问题求助

Let's work through your Vue.js 2 issues step by step:

1. Why sorting isn't working and how to fix it

The Problem

Your sorting logic has two key flaws:

  • Dynamic property access mistake: In your sort callback, you’re using a.col and b.col, but col is a variable holding the property name (like pn or od). JavaScript interprets a.col as looking for a property literally named col on the product object (which doesn’t exist), so the sort comparison does nothing.
  • Incomplete sort direction handling: Your code tries to toggle sort direction but doesn’t actually use the currentSortDir value to adjust the comparison logic. Also, Array.sort() modifies the original array in place, which can lead to unexpected behavior—better to create a copy first.

The Fix

Update your sort method to use bracket notation for dynamic property access, properly toggle the sort direction, and copy the array before sorting:

methods: {
  sort(col) {
    // Toggle direction if same column is clicked again
    if (this.currentSort === col) {
      this.currentSortDir = this.currentSortDir === 'asc' ? 'desc' : 'asc';
    } else {
      this.currentSort = col;
      this.currentSortDir = 'asc';
    }

    // Create a copy of the array to avoid mutating the original
    const sortedProducts = [...this.products].sort((a, b) => {
      const valA = a[col];
      const valB = b[col];

      // Handle numeric comparison (since your product fields are numbers)
      if (valA < valB) {
        return this.currentSortDir === 'asc' ? -1 : 1;
      }
      if (valA > valB) {
        return this.currentSortDir === 'asc' ? 1 : -1;
      }
      return 0;
    });

    this.products = sortedProducts;
  }
}
2. Restricting search to the pn column

The Solution

Use a Vue computed property to filter the products array, checking only the pn field against the search input. Computed properties automatically update whenever the search term or product data changes, making them ideal for this use case.

First, add the computed property to your Vue instance:

computed: {
  filteredProducts() {
    if (!this.search) return this.products;
    
    const searchTerm = this.search.toLowerCase();
    // Convert pn to string to handle partial matches (e.g., searching "170" finds 170158)
    return this.products.filter(product => 
      product.pn.toString().toLowerCase().includes(searchTerm)
    );
  }
}

Then update your HTML to loop over the filtered products instead of the original array:

<tr v-for="(product, index) in filteredProducts" :key="index">
  <td>{{product.pn}}</td>
  <td>{{product.od}}</td>
  <td>{{product.id}}</td>
  <td>{{product.thickness}}</td>
  <td>{{product.lo}}</td>
  <td>{{product.weight}}</td>
</tr>

Full Modified Code

HTML

<div id="app">
  <input type="text" value="" v-model="search" placeholder="Search P/N">
  <table style="text-align: center;">
    <thead>
      <tr>
        <th v-for="column in columns" :key="column.shortcode">
          <a href="#" v-on:click.prevent="sort(column.shortcode)">
            {{column.label}} 
            <!-- Optional: Add sort direction indicator -->
            {{currentSort === column.shortcode ? (currentSortDir === 'asc' ? '↑' : '↓') : ''}}
          </a>
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(product, index) in filteredProducts" :key="index">
        <td>{{product.pn}}</td>
        <td>{{product.od}}</td>
        <td>{{product.id}}</td>
        <td>{{product.thickness}}</td>
        <td>{{product.lo}}</td>
        <td>{{product.weight}}</td>
      </tr>
    </tbody>
  </table>
</div>

JavaScript

var vm = new Vue({
  el: '#app',
  data: {
    currentSort: 'pn',
    currentSortDir: 'asc',
    search: '',
    columns: [
      { label: 'P/N', shortcode: 'pn' },
      { label: 'OD (De,mm)', shortcode: 'od' },
      { label: 'ID (De,mm)', shortcode: 'id' },
      { label: 'Thickness (De,mm)', shortcode: 'thickness' },
      { label: 'LO', shortcode: 'lo' },
      { label: 'Weight (kg/1000)', shortcode: 'weight' },
    ],
    products: [
      { pn: 170158, od: 13, id: .44, thickness: 1, lo: .45, weight: .7 },
      { pn: 1803561, od: 12, id: .8, thickness: .7, lo: .11, weight: .5 },
      { pn: 170149, od: 9, id: .64, thickness: .6, lo: .75, weight: .3 },
      { pn: 150149, od: 15, id: .22, thickness: .3, lo: .55, weight: .9 },
    ],
  },
  computed: {
    filteredProducts() {
      if (!this.search) return this.products;
      
      const searchTerm = this.search.toLowerCase();
      return this.products.filter(product => 
        product.pn.toString().toLowerCase().includes(searchTerm)
      );
    }
  },
  methods: {
    sort(col) {
      if (this.currentSort === col) {
        this.currentSortDir = this.currentSortDir === 'asc' ? 'desc' : 'asc';
      } else {
        this.currentSort = col;
        this.currentSortDir = 'asc';
      }

      const sortedProducts = [...this.products].sort((a, b) => {
        const valA = a[col];
        const valB = b[col];

        if (valA < valB) {
          return this.currentSortDir === 'asc' ? -1 : 1;
        }
        if (valA > valB) {
          return this.currentSortDir === 'asc' ? 1 : -1;
        }
        return 0;
      });

      this.products = sortedProducts;
    }
  }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:09:31