Vue3 + Vant UI 实现table表格(支持下滑加载、关键词搜索)

1,088 阅读1分钟

Vue3 + Vant UI 实现移动端table表格

  1. 支持滑动加载数据,
  2. 支持关键词搜索,
  3. 支持配置表格字段,
  4. 支持宽度自适应,
  5. 支持设置列的最小宽度,超出宽度横向滚动
  6. 支持表头固定

移动端效果图

image.png

PC端效果图

image.png

代码

<template>
  <div class="activation-code-manage">
    <van-search
      v-model="searchValue"
      placeholder="请输入激活码"
      background="#fff"
      clearable
      @search="onSearch"
      @clear="onClear"
    />
    <div class="total">总计:{{ total }}个</div>
    <div class="list-wrapper">
      <ul class="header">
        <li class="column-large">激活码</li>
        <li>版本</li>
        <li>状态</li>
        <li class="column-large">订单号</li>
        <li>来源</li>
      </ul>
      <van-list
        v-model:loading="loading"
        :finished="finished"
        finished-text="没有更多了"
        @load="onLoad"
      >
        <ul v-for="(item, index) in dataList" :key="item.id">
          <li class="column-large">
            {{ item.activationCode }}
          </li>
          <li>{{ item.bindingVersionDes }}</li>
          <li>{{ item.statusDesc }}</li>
          <li class="column-large">{{ item.orderNo }}</li>
          <li>
            {{ item.sourceDesc }}
          </li>
        </ul>
      </van-list>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref } from "vue";
import { useRequest } from "@xus/vue-reuse";
import { getActivationCodeInMine } from "@/api/activation-code-manage";
import { Toast } from "vant";
const currentAgency: any = ref({
  orgCode: "1953015",
});
const searchValue = ref("");
const dataList: any = ref([]);
const total = ref(0);
const page = ref(1);
const finished = ref(false);
const { run: runList, loading: loading } = useRequest(getActivationCodeInMine, {
  manual: true,
  onSuccess: (res) => {
    total.value = res.total;
    dataList.value = [...dataList.value, ...res.records];
    page.value++;
    if (dataList.value.length >= res.total) {
      finished.value = true;
    }
  },
  onError: (err) => {
    Toast(err.message);
  },
});
const getList = () => {
  const req = {
    keyword: searchValue.value,
    pageNum: page.value,
    pageSize: 10,
  };
  runList(currentAgency.value.orgCode, req);
};
const onSearch = () => {
  page.value = 1;
  dataList.value = [];
  getList();
};
const onClear = () => {
  searchValue.value = "";
  page.value = 1;
  dataList.value = [];
  getList();
};
const onLoad = () => {
  if (currentAgency.value.orgCode) {
    getList();
  }
};
</script>

<style lang="scss" scoped>
.activation-code-manage {
  background: white;
  overflow: hidden;
  height: calc(100vh - 95px);
  display: flex;
  flex-direction: column;
  .total {
    height: 20px;
    line-height: 20px;
    font-size: 20;
    font-weight: 600;
    margin: 5px 15px;
  }
  .list-wrapper {
    flex: 1;
    background: white;
    overflow: auto;
    margin: 5px 15px;
    position: relative; // 添加相对定位
    .header {
      background: #5b87ff;
      color: white;
      border: none;
      position: sticky; // 使用 sticky 定位
      top: 0; // 固定在顶部
      z-index: 1; // 确保在内容之上
    }
    ul {
      min-width: 620px;
      padding: 10px;
      border-bottom: 1px solid #cacaca;
      display: flex;
      justify-content: space-between;
      flex-wrap: nowrap;
      li {
        width: 100px;
        font-weight: 500;
        display: inline-block;
      }
      .column-large {
        width: 160px;
      }
    }
  }
}
</style>