欢迎来到代码驿站!

vue

当前位置:首页 > 网页前端 > vue

vue对el-autocomplete二次封装增加下拉分页

时间:2022-12-31 12:21:24|栏目:vue|点击:

项目中的联想输入框现在都是采用的el-autocomplete实现的,但是随着数据量越来越多,产品要求一次不要返回所有的联想数据,要做分页处理,所以需要添加一个分页的功能。

注:看懂下面的代码需要先对vue和element有一定的学习。

废话不多数,先上完整代码

<template>
  <el-autocomplete
    ref="autocomplete"
    value-key="value"
    v-scrollLoad="selectLoadMore"
    v-loading="loading"
    v-model="state"
    :fetch-suggestions="querySearch"
    :placeholder="placeholder"
    :trigger-on-focus="false"
    @select="handleSelect"
  ></el-autocomplete>
</template>

<script>
export default {
  name: 'InputLoadMore',
  props: {
    // 封装的查数据方法
    getOptionFn: {
      require: true
    },
    // 后端定义的联想的key
    searchKey: {
      type: String,
      require: true
    },
    // v-model的绑定值
    value: {
      type: String,
      require: true
    },
    // placehoder
    placeholder: {
      type: String,
      default: '请输入'
    }
  },
  data() {
    return {
      state: '',
      loading: false,
      page: 1,
      pageTotal: 0
    }
  },
  watch: {
    state(val) {
      this.$emit('input', val)
    },
    value(val) {
      this.state = val
    }
  },
  directives: {
    // 自定义指令,监听下拉框的滚动,滚动到底部就加载下一页
    scrollLoad: {
      bind(el, binding, vnode) {
        let wrapDom = el.querySelector('.el-autocomplete-suggestion__wrap')
        let listDom = el.querySelector('.el-autocomplete-suggestion__wrap  .el-autocomplete-suggestion__list')
        wrapDom.addEventListener(
          'scroll',
          e => {
            // 注意load的使用,节流
            let condition = wrapDom.offsetHeight + wrapDom.scrollTop + 10 - listDom.offsetHeight
            if (condition > 0 && !vnode.context.loading) {
              //滚动到底部则执行滚动方法load,binding.value就是v-scrollLoad绑定的值,加()表示执行绑定的方法
              binding.value()
            }
          },
          false
        )
      }
    }
  },
  methods: {
    async querySearch(queryString, cb) {
      this.page = 1
      this.loading = true
      try {
        let { result } = await this.getOptionFn({
          page: 1,
          pageSize: 50,
          [this.searchKey]: queryString
        })
        // 根据实际情况修改下面的代码,展示数据
        if (result.rows) {
          let arr = []
          result.rows.forEach(item => {
            arr.push({ value: item })
          })
          cb(arr)
        } else {
          cb([])
        }
        this.pageTotal = result.total || 0
      } catch(e) {
        // console.log(e)
      } finally {
        this.loading = false
      }
    },
    handleSelect(item) {},
    // 加载更多
    async selectLoadMore() {
      if(Number(this.pageTotal) <= this.$refs['autocomplete'].$data.suggestions.length) {
        return
      }
      this.page = this.page + 1
      this.loading = true
      try {
        let { result } = await this.getOptionFn({
          page: this.page,
          pageSize: 50,
          [this.searchKey]: this.state
        })
        // 根据实际情况修改下面的代码,展示数据
        if (result.rows) {
          const arr = result.rows.map(item => {
            return { value: item }
          })
          // 将数据添加到下拉列表
          this.$refs['autocomplete'].$data.suggestions = this.$refs['autocomplete'].$data.suggestions.concat(arr)
        }
        this.pageTotal = result.total || 0
      } catch(e) {
        // console.log(e)
      } finally {
        this.loading = false
      }
    }
  }
}
</script>
</script>

下面对主要的地方进行讲解。

1.自定义指令实现下拉加载更多。

主要代码

// 自定义指令,监听下拉框的滚动,滚动到底部就加载下一页
    scrollLoad: {
      bind(el, binding, vnode) {
        let wrapDom = el.querySelector('.el-autocomplete-suggestion__wrap')
        let listDom = el.querySelector('.el-autocomplete-suggestion__wrap  .el-autocomplete-suggestion__list')
        wrapDom.addEventListener(
          'scroll',
          e => {
            // 注意load的使用,节流
            let condition = wrapDom.offsetHeight + wrapDom.scrollTop + 10 - listDom.offsetHeight
            if (condition > 0 && !vnode.context.loading) {
              //滚动到底部则执行滚动方法load,binding.value就是v-scrollLoad绑定的值,加()表示执行绑定的方法
              binding.value()
            }
          },
          false
        )
      }

上面主要是运用了vue的自定义指令的bind钩子。不太了解的可以先看这个https://cn.vuejs.org/v2/guide/custom-directive.html 。bind有四个参数(el、binding、vnode、oldVnode)这里用前三个,el代表绑定的元素,用来操作dom,这里用来添加scroll事件,以及计算下拉框是否滑动到底部(注意计算中的+10高度);binding是一个对象,包含旧值、新值、指令名等,这里主要用绑定值value,用来执行加载更多的方法;Vnode指的是虚拟节点,这里取他的context即为this控制loading来节流。

2.增加props(getOptionFn、searchKey、value、placeholder)抽离业务。成为公共组件

  • getOptionFn为接口封装的方法。fetch-suggestions和加载更多里面都要用到
  • searchKey表示接口需要传的参数的key,不同的接口的key可能不一致。
  • value是外面v-modle的绑定值,注意在watch里面设置值,不知道的可以看看v-model的实现原理。
  • placeholder不解释

3.可能需要解释的

  • 在加载到更多数据后怎么把输入加到下拉里面?
this.$refs['autocomplete'].$data.suggestions // 下拉的列表
  • 怎么避免加载完了还加载更多。

这里是用的数量比较,也可以加一个标识符,加载完了设置为true,变化条件后设为false。

if(Number(this.pageTotal) <= this.$refs['autocomplete'].$data.suggestions.length) {
    return
  }

上一篇:axios解决高并发的方法:axios.all()与axios.spread()的操作

栏    目:vue

下一篇:没有了

本文标题:vue对el-autocomplete二次封装增加下拉分页

本文地址:http://www.codeinn.net/misctech/222658.html

推荐教程

广告投放 | 联系我们 | 版权申明

重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:914707363 | 邮箱:codeinn#126.com(#换成@)

Copyright © 2020 代码驿站 版权所有