首页 > 其他分享 >封装el-select滚动底部加载更多

封装el-select滚动底部加载更多

时间:2024-06-08 10:58:29浏览次数:28  
标签:el 封装 String pageSize default value type page select

封装el-select滚动底部加载更多

vue2 实现el-select 下拉列表滚动加载更多数据

在这里插入图片描述

父组件页面使用

<template>
  <LoadMoreSelect
    v-model="selectValue"
    :fetchOptions="fetchStockLocationData"
    keyField="Cid"
    labelField="Code"
    valueField="Cid"
    :initialPage="initialPage"
    :pageSize="pageSize"
  />
</template>

<script>
import LoadMoreSelect from "../components/LoadMoreSelect/index.vue";
import { mapActions } from "vuex";

export default {
  name: "LoadMore",
  components: {
    LoadMoreSelect,
  },
  data() {
    return {
      selectValue: null,
      initialPage: 1,
      pageSize: 15,
    };
  },
  methods: {
    ...mapActions({
      getStockLocationDataAction: "stock/getStockLocationDataAction",
    }),
    async fetchStockLocationData({ page, pageSize }) {
      const response = await this.getStockLocationDataAction({
        page_no: page,
        page_size: pageSize,
        all: false,
        detail: false,
      });
      return response;
    },
  },
};
</script>

子组件主要代码 components/LoadMoreSelect/index.vue

<template>
  <el-select
    :placeholder="placeholder"
    v-model="internalValue"
    @change="handleChange"
    size="mini"
    clearable
  >
    <el-option
      v-for="item in options"
      :key="item[keyField]"
      :label="item[labelField]"
      :value="item[valueField]"
    >
      <span style="float: left; font-size: 12px">{{ item.Code }}</span>
      <span
        style="float: right; color: #8492a6; font-size: 12px; margin-left: 5px"
        >{{ item.Description }}</span
      >
    </el-option>
    <ElSelectLoading
      :page="currentPage"
      :loading="loading"
      :hasMore="hasMore"
      @loadMore="handleLoadMore"
    />
  </el-select>
</template>

<script>
import ElSelectLoading from "./ElSelectLoading.vue";

export default {
  components: {
    ElSelectLoading,
  },
  props: {
    //选中值
    value: {
      type: [String, Number],
      default: null,
    },
    placeholder: {
      type: String,
      default: "please select",
    },
    //异步请求
    fetchOptions: {
      type: Function,
      required: true,
    },
    keyField: {
      type: String,
      default: "id",
    },
    labelField: {
      type: String,
      default: "name",
    },
    valueField: {
      type: String,
      default: "id",
    },
    initialPage: {
      type: Number,
      default: 1,
    },
    pageSize: {
      type: Number,
      default: 10,
    },
  },
  data() {
    return {
      internalValue: this.value,
      options: [],
      loading: false,
      hasMore: true,
      currentPage: this.initialPage,
    };
  },
  watch: {
    value(newVal) {
      this.internalValue = newVal;
    },
    internalValue(newVal) {
      this.$emit("input", newVal);
    },
  },
  mounted() {
    this.loadOptions(this.currentPage, this.pageSize);
  },
  methods: {
    async loadOptions(page, pageSize) {
      if (this.loading) return;
      this.loading = true;
      try {
        const res = await this.fetchOptions({ page, pageSize });
        const list = res.data.list || [];
        if (page === this.initialPage) {
          this.options = [];
        }
        this.options.push(...list);
        this.hasMore = this.options.length < res.data.total;
        this.currentPage = page;
      } catch (error) {
        console.error(error);
      } finally {
        this.loading = false;
      }
    },
    handleLoadMore() {
      this.loadOptions(this.currentPage + 1, this.pageSize);
    },
    handleChange(value) {
      this.internalValue = value;
      this.$emit("change", value);
    },
  },
};
</script>

<style scoped lang="scss"></style>

底部的加载状态 ./ElSelectLoading.vue

<template>
  <el-select
    :placeholder="placeholder"
    v-model="internalValue"
    @change="handleChange"
    size="mini"
    clearable
  >
    <el-option
      v-for="item in options"
      :key="item[keyField]"
      :label="item[labelField]"
      :value="item[valueField]"
    >
      <span style="float: left; font-size: 12px">{{ item.Code }}</span>
      <span
        style="float: right; color: #8492a6; font-size: 12px; margin-left: 5px"
        >{{ item.Description }}</span
      >
    </el-option>
    <ElSelectLoading
      :page="currentPage"
      :loading="loading"
      :hasMore="hasMore"
      @loadMore="handleLoadMore"
    />
  </el-select>
</template>

<script>
import ElSelectLoading from "./ElSelectLoading.vue";

export default {
  components: {
    ElSelectLoading,
  },
  props: {
    //选中值
    value: {
      type: [String, Number],
      default: null,
    },
    placeholder: {
      type: String,
      default: "please select",
    },
    //异步请求
    fetchOptions: {
      type: Function,
      required: true,
    },
    keyField: {
      type: String,
      default: "id",
    },
    labelField: {
      type: String,
      default: "name",
    },
    valueField: {
      type: String,
      default: "id",
    },
    initialPage: {
      type: Number,
      default: 1,
    },
    pageSize: {
      type: Number,
      default: 10,
    },
  },
  data() {
    return {
      internalValue: this.value,
      options: [],
      loading: false,
      hasMore: true,
      currentPage: this.initialPage,
    };
  },
  watch: {
    value(newVal) {
      this.internalValue = newVal;
    },
    internalValue(newVal) {
      this.$emit("input", newVal);
    },
  },
  mounted() {
    this.loadOptions(this.currentPage, this.pageSize);
  },
  methods: {
    async loadOptions(page, pageSize) {
      if (this.loading) return;
      this.loading = true;
      try {
        const res = await this.fetchOptions({ page, pageSize });
        const list = res.data.list || [];
        if (page === this.initialPage) {
          this.options = [];
        }
        this.options.push(...list);
        this.hasMore = this.options.length < res.data.total;
        this.currentPage = page;
      } catch (error) {
        console.error(error);
      } finally {
        this.loading = false;
      }
    },
    handleLoadMore() {
      this.loadOptions(this.currentPage + 1, this.pageSize);
    },
    handleChange(value) {
      this.internalValue = value;
      this.$emit("change", value);
    },
  },
};
</script>

标签:el,封装,String,pageSize,default,value,type,page,select
From: https://blog.csdn.net/qq_52132550/article/details/139543754

相关文章

  • Android Media Framework(四)Non-Tunneled组件的状态转换与buffer分配过程分析
    本篇将继续深入OpenMAXILSpec,详细解析Non-tunneled(非隧道)组件的初始化、数据传递以及组件销毁过程。通过阅读本篇内容,我们应能对Non-tunneled组件的buffer分配与状态转换过程有一个清晰的了解。1、组件初始化以下是ILSpec给的Non-tunneled组件初始化时序图:ILClient首先......
  • [Tkey] CodeForces 1267G Game Relics
    太神了这题,膜拜出题人orz。思考一首先是大家都提到的一点,先抽卡再买。这里来做个数学分析。假设我们还剩\(k\)种没有买,其实我们是有式子来算出它的花费期望的。WIKI上提到,假设一个事件的概率为\(p\),则遇到它的期望为\(\frac{1}{p}\),因此,对于这个题,抽到一个新物品的概率显......
  • element-ui el-table表格固定表头代码示例
    在使用element-ui的el-table组件时,固定表头是一个常见的需求,特别是当表格内容较多时。以下是固定表头的一个基本示例代码:<template><el-table:data="tableData"style="width:100%"height="300px"><el-table-columnprop="date"label="日期"......
  • 覆盖路径规划经典算法 The Boustrophedon Cellular Decomposition 详解
    2000年一篇论文CoverageofKnownSpaces:TheBoustrophedonCellularDecomposition横空出世,解决了很多计算机和机器人领域的覆盖路径问题,今天我来详细解读这个算法。TheBoustrophedonCellularDecomposition算法详解这篇论文标题为"CoveragePathPlanning:TheB......
  • Spring AI 第二讲 之 Chat Model API 第八节Anthropic 3 Chat
    AnthropicClaude是一系列基础人工智能模型,可用于各种应用。对于开发人员和企业来说,您可以利用API访问,直接在Anthropic的人工智能基础架构之上进行构建。SpringAI支持用于同步和流式文本生成的Anthropic消息API。Anthropic的Claude模型也可通过AmazonBedrock......
  • 苹果将推出“Apple Intelligence”AI系统,专注于隐私和广泛应用|TodayAI
    据彭博社报道,苹果公司将在下周的 WWDC2024 开发者大会上揭晓其全新的AI系统——“AppleIntelligence”,该系统将适用于iPhone、iPad和Mac设备。这一新系统将结合苹果自身技术和OpenAI的工具,为用户提供一系列新的AI功能,同时重点关注隐私保护和广泛应用。与其他......
  • [ABC354F] Useless for LIS
    写在最前面的话:如果你懂这道题的线段树或者树状数组解法,那么本题解对你可能没有帮助。题目传送门(Luogu)题目传送门(AtCoder)[ABC354F]UselessforLIS题面翻译给定一个长度为\(n\)的序列\(a\)。求出所有\(i\)使得存在任意一个\(a\)的最长上升子序列包含\(i\)。多测。......
  • Django上传图片时ImageField的max_length报错
    我使用的版本是Django4.2,有一个模型里定义了ImageField,以下面这个为例:classExample(models.Model)image=models.ImageField(blank=True,upload_to=my_image_path,)当我上传图片的时候,django返回了这样一个错误:Ensurethisfilenam......
  • vue3 + arcgis.js4.x---线段SimpleLineSymbol
    //polylineconstpolylineGraphic=newGraphic()polylineGraphic.geometry={type:'polyline',paths:[[117.227239,31.820586],[116.227239,33.820586]]}polylineGraphic.symbol=newSimpleLineSymbol({color:'#ff0000&#......
  • [ABC126D] Even Relation 题解
    题意对一棵有$N$个点,$N-1$条边的树进行黑白染色,使得每两个距离为偶数的点颜色都一致。思路首先让我们回顾一下加法的性质:偶$+$偶$=$偶奇$+$奇$=$偶偶$+$奇$=$奇不难看出,距离为偶数的关系是可以传递的,而距离为奇数的关系不行。我们只需要做一遍dfs,对一个......