vue2中封装element ui 下拉搜索带列表滚动分页

569 阅读1分钟

话不多说,先上效果图

image.png

这里是将它变成一个组件去使用,可以多个页面引入使用

一.模板界面部分

<!-- 这个是下拉带搜索组件
   -->
<!-- :style="{'width':_width,'height':_height}" -->
<template>
  <div class="about">
    <el-select
      ref="select"
      v-model="selectVal"
      :disabled="disabled"
      :placeholder="placeholders"
      size="mini"
      clearable
      :style="{ width: widths }"
      @blur="clearData"
      @visible-change="visibleChange"
    >
      <!-- // 设置一个input框用作模糊搜索选项功能 -->
      <el-input
        v-model="keyWordFilter"
        class="input"
        placeholder="此处键入'关键词'搜索查询"
        prefix-icon="el-icon-search"
        clearable
        @input="handleInput"
        @clear="clear"
      ></el-input>
      <!-- // 设置一个隐藏的下拉选项,选项显示的是汉字label,值是value //
        如果不设置一个下拉选项,下面的树形组件将无法正常使用 -->
      <el-option key="id" hidden :value="selectVal" :label="selectVal">
      </el-option>
      <div ref="container" class="down">
        <ul ref="list">
          <li
            v-for="(item, index) in searchList"
            :key="index"
            @click.stop="handleSearchList(item)"
          >
            {{ item.number }}
          </li>
          <li v-show="searchResult" style="text-align: center">暂无搜索结果</li>
          <li v-if="loading" style="text-align: center">加载中...</li>
        </ul>
      </div>
      <!-- <div v-show="searchResult">暂无搜索结果</div> -->
    </el-select>
  </div>
</template>
<script>
import { getBelong } from "@/api/ctm/ctm-add";
import { getServiceNumber } from "@/api/admin/sys-user";
export default {
  name: "Dorpdown",
  props: {
    url: {
      type: String,
      default: () => null,
    },
    widths: {
      type: String,
      default: () => null,
    },
    disabled: {
      type: Boolean,
      default: () => false,
    },
    placeholders: {
      type: String,
      default: () => null,
    },
  },
  data() {
    return {
      selectVal: "", // select框的绑定值
      selectName: "", // select框显示的name
      keyWordFilter: "", // 搜索框绑定值,用作过滤
      solist: [], // 搜索存储列表
      searchList: [], // 接口返回搜索
      loading: false,
      // 查询参数
      queryParams: {
        pageIndex: 1,
        pageSize: 10,
        number: "",
      },
      // 总条数
      total: 0,
      searchResult: false,
      timer: null,
    };
  },
  watch: {
    keyWordFilter: {
      handler(v) {
        if (!v) {
          this.searchResult = false;
          this.searchList = [];
        }
      },
    },
    searchResult(n) {
      console.log(n);
    },
  },
  mounted() {
    this.$nextTick(() => {
      this.scrollToBottom();
    });
  },
  beforeDestroy() {
    // 移除滚动事件监听
    window.removeEventListener("scroll", this.handleScroll, true);
  },
  methods: {
    scrollToBottom() {
      const container = this.$refs.container;
      const list = this.$refs.list;
      // 滚动到底部
      list.scrollTop = container.offsetHeight - list.offsetHeight;
      // 监听滚动事件
      list.addEventListener("scroll", this.handleScroll);
    },
    handleScroll() {
      const container = this.$refs.container;
      const list = this.$refs.list;
      // 判断是否滚动到底部
      if (
        list.scrollTop >=
        container.offsetHeight - 60 // 在底部前10像素进行判断,可根据需要调整
      ) {
        console.log(list.offsetHeight, "list.offsetHeight");
        // 在这里执行滚动到底部后的逻辑
        console.log(this.searchList.length, "this.searchList.length");
        if (this.searchList.length < this.total) {
          this.queryParams.pageIndex++;
          this.search();
        }
      }
    },
    clearData() {
      this.keyWordFilter = "";
      this.queryParams.pageIndex = 1;
    },
    visibleChange(e) {
      if (!e) {
        this.searchList = [];
        this.clearData();
      } else {
        this.search();
      }
    },
    // 根据关键字搜索
    handleInput() {
      if (this.timer) {
        clearTimeout(this.timer);
      }
      this.timer = setTimeout(() => {
        this.searchList = [];
        this.queryParams.pageIndex = 1;
        this.queryParams.pageSize = 30;
        this.search();
      }, 300);
    },
    // 模拟搜索防抖
    async search() {
      this.queryParams.number = this.keyWordFilter;

      this.loading = true;
      let res;
      if (this.url === "addCtm") {
        res = await getBelong(this.queryParams);
      } else {
        res = await getServiceNumber(this.queryParams);
      }
      if (res.code === 200) {
        this.searchList = [...this.searchList, ...res.data.list];
        this.loading = false;
        console.log(this.searchList, "dorpdown");
        if (this.searchList.length === 0) {
          this.searchResult = true;
        } else {
          this.searchResult = false;
        }
        this.total = res.data.count;
      }
    },
    // 搜索框图标清空
    clear() {
      this.searchList = [];
      this.queryParams.pageIndex = 1;
      this.queryParams.pageSize = 10;
    },
    //   搜索列表点击
    handleSearchList(item) {
      this.selectVal = item.number;
      this.selectVal2 = item;
      console.log(this.selectVal2, "aa");
      this.$emit("modelClass", this.selectVal2);
      // this.$emit("modelOrigin", this.selectVal);
      this.visibleChange();
      this.$refs.select.blur();
    },
    //   清空值v-model的select值
    clearSelcet() {
      this.selectVal = "";
    },
  },
};
</script>
<style lang="scss" scoped>
::v-deep .el-scrollbar__bar {
  overflow-x: hidden;
}

::v-deep .el-input--mini .el-input__inner {
  height: 32px;
}

.input {
  width: 278px;
  margin: 10px;
}

.down {
  width: 298px;
  max-height: 120px;

  ul {
    width: 298px;
    max-height: 120px;
    overflow-y: scroll;
    margin: 0;
    padding: 0 12px;
    list-style: none;

    &::-webkit-scrollbar {
      /*滚动条整体样式*/
      width: 8px;
      /*高宽分别对应横竖滚动条的尺寸*/
      height: 1px;
    }

    &::-webkit-scrollbar-thumb {
      /*滚动条里面小方块*/
      border-radius: 10px;
      background: #1890ff;
      box-shadow: inset 0 0 5px rgb(59, 193, 230);
    }

    //滚动条底层颜色!
    &::-webkit-scrollbar-track {
      border-radius: 10px;
      background: #ededed;

      /*滚动条里面轨道*/
      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.1);
    }

    li {
      overflow: hidden; // 溢出隐藏
      white-space: nowrap; // 强制一行
      text-overflow: ellipsis; // 文字溢出显示省略号
      cursor: pointer;

      &:hover {
        color: rgb(0, 81, 255);
      }
    }
  }
}
</style>

页面引入使用

const  dorpdown = () => import('../component/dorpdown.vue')
 <el-col :span="6">
                <el-form-item label="归属工号" prop="belong">
                  <dorpdown
                    ref="childDown"
                    :widths="widths"
                    :url="'addCtm'"
                    @modelClass="changeModelClass"
                  ></dorpdown>
                </el-form-item>
              </el-col>
      
```js
   // 下拉搜索选择事件
changeModelClass(e) {
  this.form.userId = e.userId;
  this.$set(this.form, "belong", e.number);
  console.log(this.form.belong, "this.modelClass");
  console.log(e.number);
},
  // 重置按钮
resetForm(formName) {
  this.form = {};
  // 直接调用子组件方法清空值
  this.$refs.childDown.clearSelcet();
  this.$refs.form.resetFields();
  // this.$refs[formName].resetFields();
  this.$message.success("重置成功");
},
},

文章简洁明了,cv可看效果,希望可以帮助到正在看的你