PaginationSearchSelect - 自定义分页搜索选择器组件 - Antdv 选择器在数据量多时卡死卡顿问题解决方案

一、 问题说明及解决方案

1. 问题说明

主要问题来源来自一个下拉框中有四千多条数据,默认官方的Select会一次性加载所有数据,并不含分页加载功能。
在性能较差的电脑上会造成页面卡死、卡顿等情况,搜索速度过慢。

2. 解决方案

根据官方文档:选择器 Select

事件名称说明回调参数
popupScroll下拉列表滚动时的回调function

通过该事件我们可以获取滚动时Scroll的高度及最低高度,这样我们便可以进行动态的数据加载。

配合a-spin组件 可以带来比较好的用户体验

二、 组件使用说明

1. 前端组件说明

1.1 必选项
参数说明类型传参Demo
listUrl数据请求地址String
valueName下拉框value的NameStringvalueName="id"即:value=“item.id”
showNameArr下拉项中显示的名称数组,多个通过“-”进行连接Array:showNameArr="[‘name’,‘id’]"
1.2 选传项
参数说明类型默认值
multiple设置 Select 的模式为多选Booleanfalse
placeholder默认提示文字String请输入
pageSize默认分页加载条数Number10
openSearch是否开启搜索功能Booleanfalse
triggerChange回调值的方式,使用v-decorator需要传入trueBooleanfalse

2. 后端接口说明

2.1 必接项
参数说明类型
pageNo分页起始值Integer
pageSize默认分页条数Integer
2.2 选接项
参数说明类型
searchWorld查询条件String
2.3 例

使用Page及IPage进行查询封装,返回使用Result.ok(demoList)

说明:看个人情况使用分页方式,手动传入也是可以的

Page<Object> page = new Page<Standard>(Object, pageSize);
IPage<Object> pageList = testService.getList(page,searchWorld);
return Result.OK(pageList);

三、 组件代码

<template>
  <a-spin :spinning="spinning" tip="加载中...">
    <a-select
      :show-search="openSearch"
      :placeholder="placeholder"
      @popupScroll="popupScroll"
      @search="onSearch"
      @change="change"
      optionFilterProp="children"
      :value="getValueSting"
    >
      <a-select-option v-for="(item, index) in dataList" :key="index" :value="item[valueName]">
        {{ showNames(item) }}
      </a-select-option>
    </a-select>
  </a-spin>
</template>

<script>
import { getAction } from '../../api/manage'
export default {
  name: 'PaginationSearchSelect',
  props: {
    placeholder: {
      type: String,
      default: '请输入',
      required: false,
    },
    listUrl: {
      type: String,
      required: true,
    },
    valueName: {
      type: String,
      required: true,
    },
    pageSize: {
      type: Number,
      default: 10,
      required: false,
    },
    openSearch: {
      type: Boolean,
      default: false,
      required: false,
    },
    showNameArr: {
      type: Array,
      required: true,
    },
    value: {
      type: [String,Number],
      required: false,
    },
    triggerChange: {
      type: Boolean,
      default: false,
      required: false,
    }
  },
  data() {
    return {
      dataList: [],
      pageNo: 1,
      max: false,
      spinning: false,
      searchWorld: undefined,
    }
  },
  mounted() {
    this.loadDatas()
  },
  methods: {
    loadDatas() {
      this.pageNo = 1
      var param = {
        pageNo: this.pageNo,
        pageSize: this.pageSize,
        searchWorld: this.searchWorld,
      }
      getAction(this.listUrl, param).then((res) => {
        if (res.success) {
          this.dataList = res.result.records
        }
      })
    },
    showNames(item){
        var str = [];
        this.showNameArr.forEach(element => {
          str.push(item[element]);
        });
        return str.join(' - ');
    },
    filterOption(input, option) {
      return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
    },
    //滚动条滚动监听方法
    async popupScroll(e) {
      const that = this
      const { target } = e
      const scrollHeight = target.scrollHeight - target.scrollTop //滑动总高度
      const clientHeight = target.clientHeight //滑动最低高度
      // 当下拉框滚动条到达底部的时候
      if (!this.max && scrollHeight < clientHeight + 2) {
        this.spinning = true
        //数据起始条数
        this.pageNo++
        var newList = []
        var param = {
          pageNo: this.pageNo,
          pageSize: this.pageSize,
          searchWorld: this.searchWorld,
        }
        await getAction(this.listUrl, param).then((res) => {
          if (res.success) {
            newList = res.result.records
            if (newList.length == 0) {
              that.max = true
            }
          }
        })
        //数据追加
        this.dataList = this.dataList.concat(newList)
        this.spinning = false
      }
    },
    //下拉框搜索方法
    onSearch(val) {
      if (val.length != 0) {
        this.searchWorld = val
        this.dataList = []
        this.max = false
        this.loadDatas()
      } else {
        this.searchWorld = undefined
        this.dataList = []
        this.max = false
        this.loadDatas()
      }
    },
    change(val){
      if(this.triggerChange){
        this.$emit('change', val);
      }else{
        this.$emit('input', val);
      }
    }
  },
}
</script>

<style scoped>
.spin-content {
  border: 1px solid #91d5ff;
  background-color: #e6f7ff;
  padding: 30px;
}
</style>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在vue-awesome-swiper中,要自定义分页,可以使用pagination组件来进行自定义。以下是一个简单的示例: ```vue <template> <div> <swiper :options="swiperOptions"> <swiper-slide v-for="(slide, index) in slides" :key="index"> <!-- 内容 --> </swiper-slide> <!--定义分页 --> <div class="custom-pagination" slot="pagination"> <span v-for="(slide, index) in slides" :key="index" :class="{ active: index === activeIndex }" @click="goToSlide(index)" > {{ index + 1 }} </span> </div> </swiper> </div> </template> <script> import { swiper, swiperSlide } from "vue-awesome-swiper"; export default { components: { swiper, swiperSlide, }, data() { return { swiperOptions: { // 设置其他选项 }, slides: [ // 设置轮播项数据 ], activeIndex: 0, }; }, methods: { goToSlide(index) { this.activeIndex = index; }, }, }; </script> <style> .custom-pagination { /* 样式自定义 */ } .custom-pagination span { /* 样式自定义 */ } .custom-pagination span.active { /* 样式自定义 */ } </style> ``` 在这个示例中,我们首先导入`vue-awesome-swiper`的`swiper`和`swiperSlide`组件,然后在模板中使用`swiper`组件包裹轮播项,并设置`options`属性来配置其他选项。 接下来,在`swiper`组件内部,我们使用`slot`属性将自定义分页的内容放在名为"pagination"的插槽中。我们使用一个`v-for`循环来渲染分页中的每个页码,并在点击时调用`goToSlide`方法来切换轮播项。 最后,我们可以通过样式来自定义分页的外观,通过修改`.custom-pagination`和`.custom-pagination span`的样式来实现自定义效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值