自定义antd或element table 列设置组件(拖拽排序及控制是否展示)

6 篇文章 0 订阅

需求

  • 展示出所有的字段
  • 显示当前展示的是哪些字段
  • 可以全选、取消全选
  • 可以拖拽排序,更改字段的展示顺序,在前面还是在后面
  • 可以保存配置,刷新不失效

难点

  • 如何进行拖拽排序,自己手写一个吗?
  • 如何得到拖拽后的顺序?(个人觉得这个比较难)

效果

在这里插入图片描述
在这里插入图片描述

实现

  • 可以设计传入可以展示的全部字段数组当前展示字段的数组保存配置的名称,这样就能解决控制字段是否展示的需求。
  • 如何实现拖拽排序,不建议自己写,有现成的组件,而且能够返回排序后的顺序👍。推荐一个vue.draggable.next 中文文档简单好用。
  • 保存配置,这里是使用localStorage。注意踩坑:JSON.stringify不会保留函数,意味着你的一些排序函数,customRender函数会丢失。 页面进来加载配置时需要进行重新赋值

组件源码

<template>
  <a-tooltip>
    <template #title>{{ compTitle }}</template>
    <setting-outlined
      style="color: var(--theme-color)"
      @click="handleShowDrawer"
    />
  </a-tooltip>
  <a-drawer
    v-model:visible="drawerVisible"
    :title="compTitle"
    placement="right"
  >
    <div>
      <a-checkbox
        v-model:checked="checkAll"
        :indeterminate="indeterminate"
        @change="onCheckAllChange"
      >
        全选
      </a-checkbox>
      <span style="float: right">已选择 {{ checkedList.length }} 个 </span>
    </div>
    <a-checkbox-group
      class="checkbox-group"
      v-model:value="checkedList"
      @change="handleColumnChange"
    >
      <draggable
        v-model="allColumns"
        :item-key="(item) => item.dataIndex"
        handle=".move"
        animation="300"
        @end="onDragColumnEnd"
      >
        <template #item="{ element }">
          <li class="move">
            <drag-outlined style="font-size: 16px; margin-right: 10px" />
            <a-checkbox :value="element.dataIndex">
              {{ element.title }}</a-checkbox
            >
          </li>
        </template>
      </draggable>
    </a-checkbox-group>
    <template #footer>
      <div class="drawer-footer">
        <a-button @click="drawerVisible = false">取消</a-button>
        <a-button
          style="margin-left: 10px"
          type="primary"
          @click="handleSaveSetting"
          >保存</a-button
        >
      </div>
    </template>
  </a-drawer>
</template>

<script setup>
import { ref, watch, watchEffect } from 'vue'
import { message } from 'ant-design-vue'
import { SettingOutlined, DragOutlined } from '@ant-design/icons-vue'
import draggable from 'vuedraggable'

const props = defineProps({
  allColumnList: {
    // 所有列数组
    type: Array,
    default: () => []
  },
  currentColumns: {
    // 当前列数组
    type: Array,
    default: () => []
  },
  settingName: {
    type: String,
    default: 'column_setting'
  }
})
const emits = defineEmits(['columnChanged', 'columnOrderChanged'])
const compTitle = ref('列设置')
// 抽屉展示相关
const drawerVisible = ref(false)
const handleShowDrawer = () => {
  drawerVisible.value = true
}
// 选择列相关
const allColumns = ref([])
const checkedList = ref([])
watchEffect(() => {
  allColumns.value = props.allColumnList.filter(
    (item) => item.dataIndex !== 'action'
  )
  checkedList.value = props.currentColumns
    .filter((item) => item.dataIndex !== 'action')
    .map((item) => item.dataIndex)
})
// 监听列顺序改变
const onDragColumnEnd = () => {
  // console.log('列顺序改变', allColumns.value)
  // 新顺序的所有列
  const newOrderAllColumns = [
    ...allColumns.value,
    props.allColumnList[props.allColumnList.length - 1]
  ]
  emits('columnOrderChanged', newOrderAllColumns)
  // 生成新顺序的选中列
  const newOrderSelectColumns = [
    ...allColumns.value.filter((item) =>
      checkedList.value.includes(item.dataIndex)
    ),
    props.allColumnList[props.allColumnList.length - 1]
  ]
  emits('columnChanged', newOrderSelectColumns)
}
const checkAll = ref(false)
const indeterminate = ref(true) // 不定态
// 全选逻辑
const onCheckAllChange = (e) => {
  if (e.target.checked) {
    checkedList.value = allColumns.value.map((item) => item.dataIndex)
    handleColumnChange(checkedList.value)
  } else {
    checkedList.value = []
    handleColumnChange([])
  }
  indeterminate.value = false
}
watch(
  () => checkedList.value,
  (val) => {
    indeterminate.value = !!val.length && val.length < allColumns.value.length
    checkAll.value = val.length === allColumns.value.length
  }
)
// 处理列改变逻辑
const handleColumnChange = (dataIndexList) => {
  // console.log('新的值', dataIndexList, props.allColumnList)
  const newColumn = [
    ...props.allColumnList.filter((item) =>
      dataIndexList.includes(item.dataIndex)
    ),
    props.allColumnList[props.allColumnList.length - 1]
  ]
  emits('columnChanged', newColumn)
}
// 处理保存设置逻辑
const handleSaveSetting = () => {
  const setting = [...checkedList.value, 'action']
  const newOrderAllColumns = [
    ...allColumns.value,
    props.allColumnList[props.allColumnList.length - 1]
  ]
  localStorage.setItem(props.settingName, JSON.stringify(setting))
  localStorage.setItem(
    `${props.settingName}Order`,
    JSON.stringify(newOrderAllColumns)
  )
  message.success('保存成功')
  drawerVisible.value = false
}

defineExpose({
  SettingOutlined,
  DragOutlined,
  compTitle,
  draggable,
  drawerVisible,
  allColumns,
  checkedList,
  checkAll,
  indeterminate,
  handleShowDrawer,
  onCheckAllChange,
  handleSaveSetting,
  handleColumnChange,
  onDragColumnEnd
})
</script>

<style lang="less" scoped>
.checkbox-group {
  display: flex;
  flex-direction: column;
}
.drawer-footer {
  display: flex;
  justify-content: flex-end;
}
.move {
  list-style: none;
  cursor: move;
}
:deep(.ant-checkbox-wrapper + .ant-checkbox-wrapper) {
  margin-left: 0;
}
</style>

组件使用

在这里插入图片描述
在这里插入图片描述
懂得都懂

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
antdTable组件可以轻松地对时间进行排序。要在时间中实现排序,需要将时间的数据格式化为Date对象,并通过自定义的比较函数来指定排序规则。 首先,确保时间数据以Date对象的形式呈现在时间中。如果数据源中的时间数据是字符串格式,我们可以使用moment库将其解析为Date对象。 然后,在Table组件中,通过设置columns的sorter属性为一个自定义的比较函数。这个比较函数将根据两个时间值的差异来决定它们的排序顺序。在比较函数中,我们可以使用Date对象的getTime()方法获取时间的毫秒数,然后进行比较。 下面是一个示例代码: ```jsx import { Table } from 'antd'; import moment from 'moment'; // 假设data是时间数据的数组 const data = [ { id: 1, name: '张三', time: '2021-01-01 10:00:00' }, { id: 2, name: '李四', time: '2021-01-02 09:00:00' }, { id: 3, name: '王五', time: '2021-01-03 08:00:00' }, ]; // 将时间数据解析为Date对象 const formattedData = data.map(item => ({ ...item, time: moment(item.time).toDate(), })); // 创建columns对象 const columns = [ { title: 'ID', dataIndex: 'id', key: 'id', }, { title: '姓名', dataIndex: 'name', key: 'name', }, { title: '时间', dataIndex: 'time', key: 'time', sorter: (a, b) => a.time.getTime() - b.time.getTime(), // 指定比较函数 // 如果需要倒序排序,可以使用 b.time.getTime() - a.time.getTime() }, ]; // 渲染Table组件 <Table columns={columns} dataSource={formattedData} />; ``` 通过以上代码,我们可以在Table组件中对时间进行排序

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值