封装表头筛选组件并且不影响table的原有功能

 1,组件代码

<template>

  <div ref="vtable" class="relative">

    <slot name="content"> </slot>

    <a-popover

      v-model:visible="popoverVisible"

      trigger="click"

      placement="bottomRight"

      class="popover"

      :overlay-inner-style="{

        maxHeight: `${elementBottomHeight}vw`,

        overflowY: 'auto',

      }"

    >

      <template #content>

        <div

          v-for="(col, index) in allColumns"

          :key="index"

          class="checkbox-wrapper table-format"

        >

          <span v-show="col.show"> {{ col.title }}</span>

          <a-switch

            v-show="col.show"

            v-model:checked="col.open"

            size="small"

            @change="toggleColumnVisibility"

          />

        </div>

      </template>

      <template #title>

        <h1>表头设置</h1>

        <hr />

        <br />

        <a-input placeholder="搜索添加更多字段" @input="search">

          <template #prefix>

            <SearchOutlined />

          </template>

        </a-input>

      </template>

      <FunnelPlotOutlined ref="funnelIconRef" class="icon" />

    </a-popover>

  </div>

  <div ref="stickyElementRef" class="sticky"></div>

</template>

<script lang="ts" setup>

import { FunnelPlotOutlined, SearchOutlined } from '@ant-design/icons-vue'

import { inject } from 'vue'

const elementBottomHeight = ref(0)

const popoverVisible = ref(false)

const vtable = ref(null)

const stickyElementRef = ref(null)

let columns = inject('columns') as any[]

let code = columns[0].code

let allColumns: any

// 开关控制表头显示隐藏,为open为true的返回给columns

const toggleColumnVisibility = () => {

  const filteredColumns = Object.values(allColumns).filter(col => col.open)

  columns.splice(0, columns.length, ...filteredColumns)

  localStorage.setItem(code, JSON.stringify(allColumns))

}

const searchShow = () => {

  allColumns.forEach((ele: any) => {

    ele.show = true

  })

}

// 查询表头方法

const search = (event: Event) => {

  const inputValue = (event.target as HTMLInputElement).value

  const keyword = inputValue.trim().toLowerCase()

  if (keyword) {

    allColumns.forEach((ele: any) => {

      ele.show = ele.title.toLowerCase().includes(keyword) ? true : false

    })

  } else {

    allColumns.forEach((ele: any) => {

      ele.show = ele.title.toLowerCase().includes(keyword) ? true : false

    })

  }

}

onMounted(() => {

  // 优先加载本地数据要不然会影响列表的显示

  loadInitialVisibleColumns()

  // 加载了本地的数据之后,调用一次开关控制隐藏的方法,对表头为true的返回给表头

  toggleColumnVisibility()

  // 进来的时候对查询的数据进行赋值,让开关的v-show属性全部设为true

  searchShow()

  // a-popover的动态高度

  nextTick(() => {

    calculateStickyPosition()

  })

})

// 计算并设置 sticky 元素的顶部位置的函数

const calculateStickyPosition = () => {

  const funnelIconRect = vtable.value.getBoundingClientRect()

  const stickyRect = stickyElementRef.value.getBoundingClientRect()

  // 计算 FunnelPlotOutlined 图标和 sticky 元素之间的距离

  const distance = Math.abs(funnelIconRect.top - stickyRect.top)

  console.log(distance)

  elementBottomHeight.value = (distance / 1920) * 100

  console.log(elementBottomHeight.value)

}

window.addEventListener('resize', calculateStickyPosition)

// 本地获取表头

const loadInitialVisibleColumns = () => {

  let storedColumns = localStorage.getItem(code)

  if (storedColumns) {

    let parsedColumns = JSON.parse(storedColumns)

    if (Array.isArray(parsedColumns)) {

      allColumns = reactive(parsedColumns)

    } else {

      allColumns = reactive(Object.values(parsedColumns))

    }

  } else {

    allColumns = reactive([...unref(inject('columns') as any[])])

  }

}

</script>

<style lang="scss">

.table-format {

  display: flex;

  justify-content: space-between;

  margin-bottom: 10px;

}

.sticky {

  position: fixed;

  bottom: 0px;

  border: 1px solid #000;

  width: 100%;

  opacity: 0;

}

.icon {

  position: absolute;

  right: 15px;

  top: 3px;

}

</style>

2,使用方式

在需要的地方

只需要套起来

在表头的地方多添加两个字段

和子组件数据共享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值