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.colandb.col, butcolis a variable holding the property name (likepnorod). JavaScript interpretsa.colas looking for a property literally namedcolon 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
currentSortDirvalue 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
相关产品推荐
相关产品推荐

