目的
后台的 table 展示的数据很多的时候会看不过来,而且每个使用者需要看的数据可能有自己的想法。故此设计了设置字段展示的组件
技术背景:naive vue3 pinia localStorage
方案
graph TD
Page --> Pinia
Component --> Pinia
Pinia --> localStorage
localStorage --> Pinia
Page
@/views/comp/table/title.vue
import useTableStore from '@/pinia/modules/table'
import TableTitle from '@/components/Table/title.vue'
const tableStore = useTableStore()
const columns: DataTableColumns<ItemType> = [
{
title: 'Name',
key: 'name',
},
{
title: 'Age',
key: 'age',
},
]
tableStore.init(columns as { title: string; key: string }[], name)
将 columns 通过 tableStore.init 初始化,同时保证 columns 不被修改
<template>
<n-space vertical>
<TableTitle :columns="columns" :name="name"></TableTitle>
<n-data-table
:columns="tableStore.getColumns(columns, name)"
:data="dataSource"
></n-data-table>
</n-space>
</template>
html 中的 table 绑定的 columns 由 tableStore.getColumns 方法返回
Component
@/components/Table/title.vue
import { DataTableColumns, useDialog } from 'naive-ui'
import { h, PropType } from 'vue'
import CustomCheckbox from './checkbox.vue'
const dialog = useDialog()
const props = defineProps({
columns: {
required: true,
type: Array as PropType<DataTableColumns<any>>,
},
name: {
required: true,
type: String,
},
})
function custom() {
dialog.create({
title: '自定义字段设置',
showIcon: false,
style: 'width: 50vw',
content: () =>
h(
CustomCheckbox,
{
columns: props.columns,
name: props.name,
},
() => ''
),
})
}
<template>
<n-button type="primary" @click="custom">设置列表字段</n-button>
</template>
@/components/Table/checkbox.vue
import { onMounted, PropType, ref, Ref } from 'vue'
import useTableStore from '@/pinia/modules/table'
import { DataTableColumns } from 'naive-ui'
onMounted(() => {
const findItem = tableStore.data.find((v) => v.name === props.name)
list.value = findItem?.columnCheckList as string[]
})
const tableStore = useTableStore()
const props = defineProps({
columns: {
required: true,
type: Array as PropType<DataTableColumns<any>>,
},
name: {
required: true,
type: String,
},
})
// 选中 column
const list: Ref<string[]> = ref([])
function changeCheckbox(value: string[]) {
tableStore.updateColumns(value, props.name)
}
<template>
<n-checkbox-group
v-model:value="list"
@update:value="changeCheckbox"
:min="1"
>
<n-grid :x-gap="12" :y-gap="8" :cols="3">
<n-gi v-for="item in columns" :key="(item as any).key">
<n-checkbox :value="(item as any).key" :label="(item as any ).title" />
</n-gi>
</n-grid>
</n-checkbox-group>
</template>
将 table 的 column 展示成 checkbox 让使用者自由勾选需要的
这里限制至少勾选一个
Pinia
import { getTableField, setTableField } from '@/utils/auth'
import { DataTableColumns } from 'naive-ui'
import { defineStore } from 'pinia'
interface stateType {
data: {
name: string // 页面 name 唯一值
columnAllList: string[] // table 所有的 column
columnCheckList: string[] // table 展示的 column
}[]
}
const useTableStore = defineStore({
id: 'table',
state: (): stateType => ({
data: getTableField(),
}),
actions: {
/**
* 初始化,将cloumns记录到data
* @param columns table 所有的 column
* @param name 页面 name
*/
init(columns: DataTableColumns<any>, name: string) {
// 查找 data 中是否存在 name 对应的数值
const findItem = this.data.find((v) => v.name === name)
if (!findItem) {
const list: string[] = []
columns.forEach((v) => {
list.push((v as { key: string }).key)
})
this.data.push({
name,
columnAllList: list,
columnCheckList: list,
})
}
// 保存到本地
setTableField(this.data)
},
/**
* 获取页面 table 的 columns
* @param columns table 所有的 column
* @param name 页面 name
* @returns columns
*/
getColumns(columns: DataTableColumns<any>, name: string) {
const findItem = this.data.find((v) => v.name === name)
return columns.filter((v) =>
findItem?.columnCheckList.includes((v as { key: string }).key)
)
},
/**
* 设置 columns
* @param columnCheckList 页面选中的 column
* @param name 页面 name
*/
updateColumns(columnCheckList: string[], name: string) {
for (let i = 0; i < this.data.length; i++) {
if (this.data[i].name === name) {
this.data[i].columnCheckList = columnCheckList
break
}
}
// 保存到本地
setTableField(this.data)
},
},
})
export default useTableStore
localStorage
@/utils/auth.ts
import pkg from './../../package.json'
const TableField = `${name}-TableTitle`
export function getTableField() {
const listStr = localStorage.getItem(TableField) || '[]'
let list = []
try {
list = JSON.parse(listStr)
} catch (err) {}
return list
}
export function setTableField(field: any[]) {
return localStorage.setItem(TableField, JSON.stringify(field))
}
总结
这种设置列表字段的小功能可以一定程度上提升工作效率