Vuetify 2迁移:v-data-table内联过滤模板失效求助
Vuetify 2 适配 v-data-table 内联过滤的迁移方案
我刚帮你把原来Vuetify 1.x的内联过滤表格适配到Vuetify 2.x了,核心问题是Vuetify 2对v-data-table的插槽系统做了彻底更新,旧的slot="headers"和slot="items"写法已经不被支持了,下面是具体的迁移方案和修改后的完整代码:
核心迁移要点
- 插槽语法大换血:Vuetify 2.x废弃了
slot和slot-scope属性,改用v-slot(缩写#)来定义插槽,同时插槽名称也有调整:- 原
slot="headers"替换为#header(自定义整个表头区域) - 原
slot="items"替换为#item(自定义每行数据)
- 原
- 作用域变量更直观:新插槽直接提供了我们需要的变量(比如全选状态
all、半选状态indeterminate、排序字段sortBy等),不用再通过props.xxx层层获取 - 行选中逻辑简化:
#item插槽自带toggle方法,直接调用就能切换行选中状态,不用手动修改selected属性
修改后的完整代码
HTML部分
<div id="app"> <v-app id="inspire"> <v-data-table v-model="selected" :headers="headers" :items="filteredDesserts" :pagination.sync="pagination" select-all item-key="name" class="elevation-1" > <!-- 自定义表头:包含全选框、可排序表头、过滤行 --> <template #header="{ all, indeterminate, headers, sortBy, descending }"> <thead> <tr> <th> <v-checkbox :input-value="all" :indeterminate="indeterminate" primary hide-details @click.native="toggleAll" ></v-checkbox> </th> <th v-for="header in headers" :key="header.value" :class="[ 'column sortable', descending ? 'desc' : 'asc', header.value === sortBy ? 'active' : '' ]" @click="changeSort(header.value)" > <v-icon small>arrow_upward</v-icon> {{ header.text }} </th> </tr> <tr class="grey lighten-3"> <th> <v-icon>filter_list</v-icon> </th> <th v-for="header in headers" :key="header.value"> <div v-if="filters.hasOwnProperty(header.value)"> <v-select flat hide-details small multiple clearable :items="columnValueList(header.value)" v-model="filters[header.value]" ></v-select> </div> </th> </tr> </thead> </template> <!-- 自定义数据行 --> <template #item="{ item, selected, toggle }"> <tr :active="selected" @click="toggle"> <td> <v-checkbox :input-value="selected" primary hide-details ></v-checkbox> </td> <td>{{ item.name }}</td> <td class="text-xs-right">{{ item.calories }}</td> <td class="text-xs-right">{{ item.fat }}</td> <td class="text-xs-right">{{ item.carbs }}</td> <td class="text-xs-right">{{ item.protein }}</td> <td class="text-xs-right">{{ item.iron }}</td> </tr> </template> </v-data-table> </v-app> </div>
JS部分(几乎无需修改)
new Vue({ el: '#app', data: () => ({ pagination: { sortBy: 'name' }, selected: [], headers: [ { text: 'Dessert (100g serving)', align: 'left', value: 'name' }, { text: 'Calories', value: 'calories' }, { text: 'Fat (g)', value: 'fat' }, { text: 'Carbs (g)', value: 'carbs' }, { text: 'Protein (g)', value: 'protein' }, { text: 'Iron (%)', value: 'iron' } ], filters: { fat: [], carbs: [], iron: [], }, desserts: [ { value: false, name: 'Frozen Yogurt', calories: 159, fat: 6.0, carbs: 24, protein: 4.0, iron: '1%' }, { value: false, name: 'Ice cream sandwich', calories: 237, fat: 9.0, carbs: 37, protein: 4.3, iron: '1%' }, { value: false, name: 'Eclair', calories: 262, fat: 16.0, carbs: 23, protein: 6.0, iron: '7%' }, { value: false, name: 'Cupcake', calories: 305, fat: 3.7, carbs: 67, protein: 4.3, iron: '8%' }, { value: false, name: 'Gingerbread', calories: 356, fat: 16.0, carbs: 49, protein: 3.9, iron: '16%' }, { value: false, name: 'Jelly bean', calories: 375, fat: 0.0, carbs: 94, protein: 0.0, iron: '0%' }, { value: false, name: 'Lollipop', calories: 392, fat: 0.2, carbs: 98, protein: 0, iron: '2%' }, { value: false, name: 'Honeycomb', calories: 408, fat: 3.2, carbs: 87, protein: 6.5, iron: '45%' }, { value: false, name: 'Donut', calories: 452, fat: 25.0, carbs: 51, protein: 4.9, iron: '22%' }, { value: false, name: 'KitKat', calories: 518, fat: 26.0, carbs: 65, protein: 7, iron: '6%' } ] }), computed: { filteredDesserts() { return this.desserts.filter(d => { return Object.keys(this.filters).every(f => { return this.filters[f].length < 1 || this.filters[f].includes(d[f]) }) }) } }, methods: { toggleAll () { if (this.selected.length) this.selected = [] else this.selected = this.desserts.slice() }, changeSort (column) { if (this.pagination.sortBy === column) { this.pagination.descending = !this.pagination.descending } else { this.pagination.sortBy = column this.pagination.descending = false } }, columnValueList(val) { return this.desserts.map(d => d[val]) } } })
额外说明
- 原来的过滤逻辑完全保留,
filters对象和filteredDesserts计算属性不需要任何修改 - 排序逻辑和全选逻辑的核心代码也没变,只是调整了插槽中变量的获取方式
- 测试下来,修改后的代码在Vuetify 2.x版本中可以完美复现原有的所有功能:全选/取消全选、点击表头排序、下拉多选过滤数据
内容的提问来源于stack exchange,提问作者timitalia
相关产品推荐
相关产品推荐

