列表过滤与排序
列表过滤与排序的正确姿势:不要在模板里写 v-for="t in todos.filter(...)"——每次渲染都重新过滤;用 computed 派生一份「过滤并排序后的列表」,依赖变化才重算。
排序特别注意:直接 list.sort() 会改动原数组;用 [...list].sort() 先拷贝再排,避免修改源数据引发意料外的更新。
- 过滤/排序都用 computed 派生,不要在 v-for 里写方法调用
- [...arr].sort() 先拷贝再排,不污染原数组
- 升序降序切换:computed 内根据 sortKey 与 order 计算
HTML
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>列表过滤与排序</title> <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> </head> <body> <div id="app"> <input v-model="q" placeholder="按名称过滤"> <button @click="order = order === 1 ? -1 : 1">切换排序</button> <ul> <li v-for="p in filtered" :key="p.id">{{ p.name }} - {{ p.price }} 元</li> </ul> </div> <script> const { createApp, ref, computed } = Vue; createApp({ setup() { const products = ref([ { id: 1, name: '苹果', price: 6 }, { id: 2, name: '香蕉', price: 4 }, { id: 3, name: '樱桃', price: 20 } ]); const q = ref(''); const order = ref(1); // 1 升序 -1 降序 // 过滤 + 排序都由 computed 完成,自动缓存 const filtered = computed(() => { const list = products.value.filter(p => p.name.includes(q.value)); return [...list].sort((a, b) => (a.price - b.price) * order.value); }); return { q, order, filtered }; } }).mount('#app'); </script> </body> </html>
本节要点列表加工交给 computed:过滤+排序一次派生,[...arr] 先拷贝再 sort 不动原数据。




