如何在客户端对Inertia传递的数据进行排序?
客户端实现Vue组件数据排序方案(基于Inertia传递的Proxy数据)
现有代码
Laravel路由/控制器代码
Route::get('/', function() { return inertia('foo', ['data' => Model::all()]) });
Vue组件代码
<template> <ul> <li v-for="item in data">{{item.name}}</li> </ul> </template> <script setup> defineProps({ data: Object }) </script>
问题说明
需求是通过复选框选择排序字段,在客户端完成name或score字段的排序,不发起服务端请求。但存在两个阻碍:
- Vue的Props是只读属性,无法直接修改排序
- 后端传递的
data是带数字键的Proxy类数组对象,转普通Object后无法调用sort方法
解决方案
1. 先将Proxy类数组转为真实数组
后端返回的Eloquent集合被Inertia序列化为类数组对象,需要先转为真实数组才能使用数组方法。可以用Object.values()或Array.from()完成转换:
// 两种转换方式二选一 const dataArray = Object.values(props.data); // 或者 const dataArray = Array.from(props.data);
2. 用计算属性处理动态排序
利用Vue的计算属性,结合选中的排序字段返回排序后的数组,全程不修改原Props数据:
完整组件示例代码:
<template> <div> <!-- 排序选项 --> <label> <input type="radio" v-model="sortField" value="name" /> 按名称排序 </label> <label> <input type="radio" v-model="sortField" value="score" /> 按分数排序 </label> <ul> <li v-for="item in sortedData" :key="item.id"> {{ item.name }} - 分数: {{ item.score }} </li> </ul> </div> </template> <script setup> import { computed, ref } from 'vue'; const props = defineProps({ data: Object }); // 绑定当前选中的排序字段 const sortField = ref('name'); // 计算属性实时返回排序后的数据 const sortedData = computed(() => { // 转换为真实数组 const rawArray = Object.values(props.data); // 拷贝数组避免原地排序修改原数据 const sorted = [...rawArray]; // 根据选中字段执行排序 if (sortField.value === 'name') { return sorted.sort((a, b) => a.name.localeCompare(b.name)); } else if (sortField.value === 'score') { return sorted.sort((a, b) => b.score - a.score); // 降序,升序改为a.score - b.score } return sorted; }); </script>
关键细节
Object.values()能直接提取Proxy对象中的值,生成真实数组,解决无sort方法的问题- 计算属性会自动响应
sortField的变化,实时更新排序结果 - 排序前拷贝数组(
[...rawArray]),避免sort方法的原地排序特性意外影响原数据 - 字符串排序用
localeCompare,能更好处理多语言字符的排序逻辑
内容的提问来源于stack exchange,提问作者nowox
相关产品推荐
相关产品推荐

