elementui中select下拉框添加分页(可搜索)

最近遇到这样的需求,select下拉框的数据太多,导致高度很高,影响美观,所以给select下拉框添加分页功能。新建一个组件。

首先是HTML部分

这里没什么说的 ,直接嵌套即可

    <el-select
      v-model="value1"
      placeholder="选择埋点"
      :clearable="false"
      style="width: 240px"
      size="mini"
      refs="mySelect"
      :reserve-keyword="true"
      filterable
      popper-class="sele"
      :filter-method="filter"
      @change="fun"
      @focus="funx"
      @blur="funb"
      @visible-change="hidden"
    >
      <el-option
        v-for="item in optionfen"
        :key="item.value"
        :label="item.value"
        remote
        :value="item.label"
        placeholder="请输入"
      >
      </el-option>

      <div  style="bottom: -10px">
        <el-pagination
          small
          @current-change="handleCurrentChange"
          :current-page="currentpage"
          :page-size="pageSize"
          layout="prev, pager,next,total"
          :total="options.length"
        >
        </el-pagination>
      </div>
    </el-select>

CSS部分

.drop >>> .el-input__inner {
  background: #5183ff !important;
  color: white;
  border: none;
  height: 26px;
  padding: 10px 22px 10px 10px;
  text-align: center;
}
.drop {
  width: 250px;
}
.drop >>> .el-select .el-input .el-select__caret {
  display: none;
}

JS部分

这里因为数据是一次性返回的 所以自行实现了分页和搜索

export default {
  data() {
    return {
      options: [],  //总数据
      options1: [],  //搜索的数据
      optionfen: [],  //当前页码的数据
      value1: "",  //输入框的值
      currentpage: 1,   //当前页码
      pageSize: 10,   //每页展示的条数
      val: "",   
    };
  },
  props: {
  //向父组件传递数据
    funName: {
      type: String,
      require: true,
    },
    //接收返回值
    renderingAllKeys: {
      type: Array,
      require: true,
    },
  },
  computed: {},
  mounted() {},
  methods: {
  //分页的实现,currentpage 为页码,每页展示的数据为10(可自行更改pageSize)条,分别是在总数据options中
  //下标从(currentpage -1)*10开始的十条数据
    handleCurrentChange(val) {
      this.optionfen = [];
      this.currentpage = val;
      let start = (val - 1) * this.pageSize;
      let end = Number(start) + Number(this.pageSize);
      //此处需要判断如果计算的结束下标大于总数据的长度,则需要修改结束下标
      if (end > this.options.length) {
        end = this.options.length;
      }
      for (let i = start; i < end; i++) {
      //将取到的数据展示在页面
        this.optionfen.push(this.options[i]);
      }
    },
    //选择数据后将相关数据发送给父组件
    fun() {
      let arr = [];
      this.val = this.value1;
      for (let j in this.optionfen) {
        if (this.value1 == this.optionfen[j].label) {
          arr.push(this.optionfen[j]);
        }
      }
      this.$emit(`${this.funName}`, arr);
    },
    // 获得焦点
    //获得焦点的时候跳转到当前value所在的页码
    funx() {
      this.val = this.value1;
      let flag = false;
      for (let i in this.options1) {
        if (this.options1[i].label == this.value1) {
          flag = true;
          let num = Math.floor((i + 10) / 10);
          this.currentpage = Number(num);
          this.handleCurrentChange(Number(num));
        }
      }
      //如果没有就默认展示第一页
      if (!flag) {
        this.currentpage = 1;
        this.handleCurrentChange(1);
      }
    },
    // 失去焦点
    //前面每次操作都将输入框内的value值存储一份到val中,就是为了防止用户搜索的时候中途关闭选择框,这个时候输入框显示的就是
    //用户输入一半的value值,加上这层逻辑就可以在用户输入的数据在总数据中不存在的时候(也就是无效数据),关闭选择框
    //之后让输入框依旧显示上一次的正确value值
    funb() {
      this.value1 = this.val;
      $(".drop >>> .el-input__inner").css({
        color: "white",
      });
    },
    hidden(bool) {
      // 隐藏select列表
      if (!bool) {
      //关闭select下拉框的时候重置页码及数据,并移除事件监听
        this.optionfen = [];
        this.options = this.options1;
        let start = 0;
        let end = Number(start) + Number(this.pageSize);
        if (end > this.options1.length) {
          end = this.options1.length;
        }
        for (let i = start; i < end; i++) {
          this.optionfen.push(this.options1[i]);
        }
        // 移除mousedown事件监听
        removeEventListener("mousedown", function () {}, false);
      } else {
        // 打开select列表
        // 增加mousedown事件监听  当点击分页时移除输入框的默认事件 ,让他不会失去焦点(blur),如果不加,就会
        //出现当用户点击分页之后,输入框会失去焦点,这个时候如果用户需要输入数据进行搜索就需要先删除输入框的值再输入,体验不好。
        //(elementUI下拉框的默认样式,当可搜索时点击输入框可直接输入,不需要删除上次数据)
        document.addEventListener(
          "mousedown",
          function (e) {
            // console.log(e)
            if (
              e.target.tagName === "LI" ||
              (e.target.tagName == "I" && e.target.localName == "i")
            ) {
              e.preventDefault();
            }
          },
          false
        );
        this.funx();
      }
    },
    //搜索方法,将符合的数据存入options中,并分页展示
    filter(val) {
      this.optionfen = [];
      this.value1 = val;
      let arr = [];
      let value = val.toLowerCase();
      for (let i in this.options1) {
        if (this.options1[i].label.toLowerCase().indexOf(value) >= 0) {
          arr.push(this.options1[i]);
        }
      }
      this.options = arr;
      this.handleCurrentChange(1);
    },
  },
  //监听来自父组件的数据,当数据更新时,重置展示
  watch: {
    renderingAllKeys: {
      //深度监听,可监听到对象、数组的变化
      handler(newV) {
		 if(newV.length>0){
        	   this.options1 = newV;
               this.options = newV;
               this.optionfen=[]
               this.currentpage=1  //标记重置
               let start=(this.currentpage-1)*this.pageSize
               let end=Number(start)+Number(this.pageSize)
               if(end>this.options1.length){
                   end=this.options1.length
               }
               for(let i=start;i<end;i++){
                   this.optionfen.push(this.options1[i])
               }
               this.value1 = newV[0].label;  //指标重置
               this.val = newV[0].label;  //指标重置
               this.fun()
           }else{
               this.options1=[]
               this.options=[]
               this.optionfen=[]
               this.value1=""
           }
		      },
      deep: false,
    },
  },
};

父组件中使用该组件

renderingAllKeys向子组件传递父组件的数据

<dropdown
          funName="downBase"
          :renderingAllKeys="renderingAllKeys"
          :maxNum="1"
          @downBase="getDropdownInfo"
        />

父组件中使用getDropdownInfo获取来自子组件的数据

    getDropdownInfo(data) {
      this.selectTypeArr = data;
		//拿到数据执行需要的逻辑
    },

效果图

  • 8
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
要实现下拉框触底加载下一页,可以使用 `element-ui` 的 `el-select` 和 `el-option` 组件结合 `scroll` 事件来实现。具体操作如下: 1. 在 `el-select` 组件添加 `@scroll.native` 事件,绑定一个方法,用于监听下拉框的滚动事件。 2. 在绑定的方法,判断下拉框是否滚动到底部,如果滚动到底部,则触发加载下一页的方法,并将下一页的数据添加到选项。 3. 在 `el-option` 组件添加一个指令 `v-if`,用于判断当前选项是否需要显示。当选项数据为空时,不显示该选项。 下面是一个示例代码: ```html <template> <el-select v-model="value" @scroll.native="handleScroll" :filterable="filterable"> <el-option v-for="option in options" :key="option.value" :label="option.label" :value="option.value" v-if="option.label !== 'loading'"></el-option> <el-option v-if="loading" label="loading"> <template #loading> <i class="el-icon-loading"></i> </template> </el-option> </el-select> </template> <script> export default { data() { return { value: '', options: [], loading: false, filterable: true, page: 1, }; }, methods: { handleScroll(e) { const container = e.target; const scrollHeight = container.scrollHeight; const offsetHeight = container.offsetHeight; const scrollTop = container.scrollTop; if (scrollTop + offsetHeight >= scrollHeight && !this.loading) { this.loading = true; this.loadNextPage(); } }, async loadNextPage() { // 模拟异步加载数据 await new Promise((resolve) => setTimeout(resolve, 1000)); const nextPage = this.page + 1; const newOptions = Array.from({ length: 10 }, (_, index) => ({ label: `Option ${nextPage}${index + 1}`, value: `option${nextPage}${index + 1}`, })); this.options = this.options.concat(newOptions); this.page = nextPage; this.loading = false; }, }, }; </script> ``` 这样,当下拉框滚动到底部时,就会触发加载下一页的方法,并将下一页的数据添加到选项,从而实现了下拉框触底加载下一页的功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值