瀏覽代碼

feat: 新增触底请求接口加载下一页的自定义指令,封装多页码几口的下拉框远程搜索组件

mnisting 6 月之前
父節點
當前提交
6fce5d23d9
共有 3 個文件被更改,包括 168 次插入17 次删除
  1. 126 0
      src/components/SelectRemote/index.vue
  2. 19 17
      src/directive/index.js
  3. 23 0
      src/directive/module/selectLoadmore.js

+ 126 - 0
src/components/SelectRemote/index.vue

@@ -0,0 +1,126 @@
+<!-- el-select远程搜索公共组件 -->
+<template>
+  <el-select
+    style="width: 100%"
+    ref="selectRef"
+    v-loadmore="loadmore"
+    filterable
+    remote
+    @focus="getList"
+    :remote-method="remoteMethod"
+    v-model="selectId"
+    clearable
+    placeholder="请输入关键词搜索"
+    @change="onChange"
+  >
+    <el-option
+      v-for="item in options"
+      :key="item.id"
+      :label="item.selectLabel"
+      :value="item.id"
+    >
+    </el-option>
+  </el-select>
+</template>
+
+<script>
+import { getData } from "@/api/public";
+export default {
+  props: {
+    // 远程搜索的url
+    url: {
+      type: String,
+      default: "",
+    },
+    // 搜索的字段
+    field: {
+      type: String,
+      default: "",
+    },
+    value: {
+      type: Number | String,
+      default: "",
+    },
+    selectObj: {
+      type: Object,
+      default: () => {},
+    },
+  },
+  data() {
+    return {
+      options: [],
+      stopLoading: false, // 加载开关,加载所有后端数据后控制懒加载是否继续执行,通过后端返回数据来控制
+      pageNum: 1,
+      total: 0,
+      selectId: null,
+    };
+  },
+  watch: {
+    value(newVal) {
+      // console.log(newVal);
+      this.selectId = newVal;
+      this.options = [this.selectObj];
+    },
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    onChange() {
+      this.$emit("input", this.selectId);
+    },
+    // 懒加载调用的方法
+    loadmore() {
+      if (this.options.length < this.total) {
+        this.pageNum++;
+        this.remoteMethod(this.$refs.selectRef.query, true);
+      }
+
+      // if (!this.stopLoading) {
+      //   this.pageNum++; // 搜索下一页
+      //   this.remoteMethod(this.$refs.selectRef.query, true); //调用后端接口获取下拉框数据,此时第二个参数必须传 true,懒加载方式调用后端接口函数
+      // }
+    },
+    // 输入框没有值时默认请求第一页8条数据
+    getList() {
+      let params = {
+        pageNum: 1,
+        pageSize: 8,
+      };
+      getData(this.url, params).then((res) => {
+        this.options = res.rows.map((item) => {
+          return {
+            ...item,
+            selectLabel: item[this.field],
+          };
+        });
+        this.total = res.total;
+      });
+    },
+    remoteMethod(query, lazy = false) {
+      this.stopLoading = true;
+      if (!lazy) {
+        // 如果不是懒加载,
+        this.options = []; // 把select选项数组重置为空
+        this.pageNum = 1; // 设置查询第一页
+      }
+      let params = {
+        pageNum: this.pageNum,
+        pageSize: 8,
+      };
+      params[this.field] = query;
+      getData(this.url, params).then((res) => {
+        let arr = res.rows.map((item) => {
+          return {
+            ...item,
+            selectLabel: item[this.field],
+          };
+        });
+        this.options = this.options.concat(arr);
+        this.total = res.total;
+        this.stopLoading = false;
+      });
+    },
+  },
+};
+</script>

+ 19 - 17
src/directive/index.js

@@ -1,23 +1,25 @@
-import hasRole from './permission/hasRole'
-import hasPermi from './permission/hasPermi'
-import dialogDrag from './dialog/drag'
-import dialogDragWidth from './dialog/dragWidth'
-import dialogDragHeight from './dialog/dragHeight'
-import clipboard from './module/clipboard'
+import hasRole from "./permission/hasRole";
+import hasPermi from "./permission/hasPermi";
+import dialogDrag from "./dialog/drag";
+import dialogDragWidth from "./dialog/dragWidth";
+import dialogDragHeight from "./dialog/dragHeight";
+import clipboard from "./module/clipboard";
+import loadmore from "./module/selectLoadmore";
 
-const install = function(Vue) {
-  Vue.directive('hasRole', hasRole)
-  Vue.directive('hasPermi', hasPermi)
-  Vue.directive('clipboard', clipboard)
-  Vue.directive('dialogDrag', dialogDrag)
-  Vue.directive('dialogDragWidth', dialogDragWidth)
-  Vue.directive('dialogDragHeight', dialogDragHeight)
-}
+const install = function (Vue) {
+  Vue.directive("hasRole", hasRole);
+  Vue.directive("hasPermi", hasPermi);
+  Vue.directive("clipboard", clipboard);
+  Vue.directive("dialogDrag", dialogDrag);
+  Vue.directive("dialogDragWidth", dialogDragWidth);
+  Vue.directive("dialogDragHeight", dialogDragHeight);
+  Vue.directive("loadmore", loadmore);
+};
 
 if (window.Vue) {
-  window['hasRole'] = hasRole
-  window['hasPermi'] = hasPermi
+  window["hasRole"] = hasRole;
+  window["hasPermi"] = hasPermi;
   Vue.use(install); // eslint-disable-line
 }
 
-export default install
+export default install;

+ 23 - 0
src/directive/module/selectLoadmore.js

@@ -0,0 +1,23 @@
+/**
+ * v-loadmore 下拉框远程搜索触底加载(实现懒加载)
+ */
+
+export default {
+  bind(el, binding) {
+    // 下拉框对象
+    const SELECTWRAP_DOM = el.querySelector(
+      ".el-select-dropdown .el-select-dropdown__wrap"
+    );
+    // 给下拉框增加滚动监听,
+    SELECTWRAP_DOM.addEventListener("scroll", function () {
+      // scrollHeight:当前所有选项的高度
+      // scrollTop:滚动的距离
+      // clientHeight:下拉框的高度
+      const condition = this.scrollHeight - this.scrollTop <= this.clientHeight;
+      // 当滚动条滚动到最底下的时候执行接口加载下一页
+      if (condition) {
+        binding.value();
+      }
+    });
+  },
+};