经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
vue对el-autocomplete二次封装增加下拉分页
来源:jb51  时间:2022/3/8 12:55:32  对本文有异议

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

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

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

  1. <template>
  2. <el-autocomplete
  3. ref="autocomplete"
  4. value-key="value"
  5. v-scrollLoad="selectLoadMore"
  6. v-loading="loading"
  7. v-model="state"
  8. :fetch-suggestions="querySearch"
  9. :placeholder="placeholder"
  10. :trigger-on-focus="false"
  11. @select="handleSelect"
  12. ></el-autocomplete>
  13. </template>
  14.  
  15. <script>
  16. export default {
  17. name: 'InputLoadMore',
  18. props: {
  19. // 封装的查数据方法
  20. getOptionFn: {
  21. require: true
  22. },
  23. // 后端定义的联想的key
  24. searchKey: {
  25. type: String,
  26. require: true
  27. },
  28. // v-model的绑定值
  29. value: {
  30. type: String,
  31. require: true
  32. },
  33. // placehoder
  34. placeholder: {
  35. type: String,
  36. default: '请输入'
  37. }
  38. },
  39. data() {
  40. return {
  41. state: '',
  42. loading: false,
  43. page: 1,
  44. pageTotal: 0
  45. }
  46. },
  47. watch: {
  48. state(val) {
  49. this.$emit('input', val)
  50. },
  51. value(val) {
  52. this.state = val
  53. }
  54. },
  55. directives: {
  56. // 自定义指令,监听下拉框的滚动,滚动到底部就加载下一页
  57. scrollLoad: {
  58. bind(el, binding, vnode) {
  59. let wrapDom = el.querySelector('.el-autocomplete-suggestion__wrap')
  60. let listDom = el.querySelector('.el-autocomplete-suggestion__wrap .el-autocomplete-suggestion__list')
  61. wrapDom.addEventListener(
  62. 'scroll',
  63. e => {
  64. // 注意load的使用,节流
  65. let condition = wrapDom.offsetHeight + wrapDom.scrollTop + 10 - listDom.offsetHeight
  66. if (condition > 0 && !vnode.context.loading) {
  67. //滚动到底部则执行滚动方法load,binding.value就是v-scrollLoad绑定的值,加()表示执行绑定的方法
  68. binding.value()
  69. }
  70. },
  71. false
  72. )
  73. }
  74. }
  75. },
  76. methods: {
  77. async querySearch(queryString, cb) {
  78. this.page = 1
  79. this.loading = true
  80. try {
  81. let { result } = await this.getOptionFn({
  82. page: 1,
  83. pageSize: 50,
  84. [this.searchKey]: queryString
  85. })
  86. // 根据实际情况修改下面的代码,展示数据
  87. if (result.rows) {
  88. let arr = []
  89. result.rows.forEach(item => {
  90. arr.push({ value: item })
  91. })
  92. cb(arr)
  93. } else {
  94. cb([])
  95. }
  96. this.pageTotal = result.total || 0
  97. } catch(e) {
  98. // console.log(e)
  99. } finally {
  100. this.loading = false
  101. }
  102. },
  103. handleSelect(item) {},
  104. // 加载更多
  105. async selectLoadMore() {
  106. if(Number(this.pageTotal) <= this.$refs['autocomplete'].$data.suggestions.length) {
  107. return
  108. }
  109. this.page = this.page + 1
  110. this.loading = true
  111. try {
  112. let { result } = await this.getOptionFn({
  113. page: this.page,
  114. pageSize: 50,
  115. [this.searchKey]: this.state
  116. })
  117. // 根据实际情况修改下面的代码,展示数据
  118. if (result.rows) {
  119. const arr = result.rows.map(item => {
  120. return { value: item }
  121. })
  122. // 将数据添加到下拉列表
  123. this.$refs['autocomplete'].$data.suggestions = this.$refs['autocomplete'].$data.suggestions.concat(arr)
  124. }
  125. this.pageTotal = result.total || 0
  126. } catch(e) {
  127. // console.log(e)
  128. } finally {
  129. this.loading = false
  130. }
  131. }
  132. }
  133. }
  134. </script>
  135. </script>

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

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

主要代码

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

上面主要是运用了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.可能需要解释的

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

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

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

到此这篇关于vue对el-autocomplete二次封装增加下拉分页的文章就介绍到这了,更多相关vue el-autocomplete下拉分页内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号