首先简单看下需求,项目中工作台页面有个小模块,大概功能是需要实现该模块中的下拉加载数据,并且实现input框的实时输入搜索。如下图所示:
后端给出的接口已经实际上是一个支持通过患者姓名和分页参数来查询的接口,主要看一下前端如何实现,直接上重点代码:
<template>
<div
id="followData"
v-loading="loading"
element-loading-background="rgba(0, 0, 0, 0)"
class="follow-class"
>
......
<div v-if="ifDataEmpty" class="default-box">
<img src="XXXXXX" alt="">
<div class="default-txt">暂无搜索结果div>
div>
div>
template>
首先是 HTML 代码部分,这部分的重点是需要给最外层父元素一个 id ,后面需要操作 dom 元素,图中的 v-loading
是 Element-UI 的加载组件。
<style lang="scss" scoped>
.follow-class {
width: 100%;
height: 774px;
padding: 0 10px;
background: #ECF0F6;
border-radius: 7px;
border: 1px solid #FFFFFF;
overflow: scroll;
overflow-x: hidden;
&::-webkit-scrollbar {
width: 4px;
background: white;
}
&::-webkit-scrollbar-corner,
&::-webkit-scrollbar-thumb,
&::-webkit-scrollbar-track {
border-radius: 4px;
}
&::-webkit-scrollbar-corner,
&::-webkit-scrollbar-track {
background-color: rgba(180, 160, 120, 0.1);
box-shadow: inset 0 0 1px rgba(180, 160, 120, 0.5);
}
&::-webkit-scrollbar-thumb {
background-color: rgba(144,147,153,.5);
}
...... 其他CSS代码 ......
style>
CSS 代码重点部分是 height: 774px
、overflow: scroll
和 overflow-x: hidden
首先需要固定一个高度,然后将滚动条调出来,隐藏 x 轴滚动条,其他的一大段代码是设置滚动条样式的,浏览器原来的滚动条不美观。
接下来看 JS 部分代码:
先来看 data 中的数据
export default {
data() {
return {
loading: false, // Element-UI 的 loading 组件动态属性,true 的时候页面会有加载圈圈效果
title: '', // input 框的 v-model 绑定值
page: { // 分页参数,字段名按照后端给出的接口文档来
pageNumber: 1, // 当前页数,从第一页开始
pageSize: 8 // 一页要展现的数据数,按照高度来,本项目中是一页8个
},
total: '', // 记录接口返回数据的总页数
ifDataEmpty: false // 判断搜索时是否返回数据为空,空的话展示缺省图
}
}
}
再看一下 methods 中的几个重点方法:
// mounted 中需要加载的方法,给父元素绑定 scroll 事件
bindEventListener() {
// 用 $nextTick ,确保页面 dom 元素加载完毕
this.$nextTick(() => {
const el = document.getElementById('followData')
if (!el) return
// 用 lodash 做节流处理,防止滚动到底部时多次触发加载数据方法,scrollHandler 方法在下方给出
el.addEventListener('scroll', _.throttle(this.scrollHandler, 200))
})
}
// 滚动分页加载
scrollHandler() {
const divHeight = document.getElementById('followData').offsetHeight
const nScrollHeight = document.getElementById('followData').scrollHeight
const nScrollTop = document.getElementById('followData').scrollTop
if (nScrollTop + divHeight + 1 >= nScrollHeight) {
this.page.pageNumber = parseInt(this.page.pageNumber + 1)
if (this.page.pageNumber > parseInt(this.total)) {
return false
}
this.getData('1') // 请求数据,getData 方法在下方给出
}
}
关于 offsetHeight、scrollHeight、scrollTop 这三个属性一定要了解,不清楚的可以自寻网上学习。
本方法主要是用于判断滚动条是否滚动到最底部。若滚动到最底部的时候,将 pageNumber 自加一,如果此时的 pageNumber 小于总页数,就请求下一页的数据;如果大于总页数,就 return 出来,因为已经是最后一页了,不需要再请求数据了。
然后就是请求接口数据的方法:
/** 请求分页接口的函数方法
* @method getData
* @param {string} type type为1:整页查询;type为2:搜索查询
*/
getData(type) {
this.loading = true // 请求接口前将 loading 圈圈的效果放出
getPageList({ // 项目已经全局封装 axios 请求了,这里的写法不尽相同,不一定是我这样的
title: this.title // 入参为 input 框的内容和 page 参数
}, this.page).then(res => {
this.loading = false // 请求成功后将 loading 圈圈效果停止掉
const _result = res
const _data = _result.content // 接口返回的数据是 res 的 content 属性,这里按照接口返回格式来赋值
this.total = _result.totalPages // 记录接口返回数据的总页数
// 页面刚加载完直接展示的话数据是拼接在后面的,搜索框实时展示的话数据是重新赋值
type === '1' ? this.followList = this.followList.concat(_data) : this.followList = _data
if (type === '2') {
_data.length === 0 ? this.ifDataEmpty = true : this.ifDataEmpty = false // 是否展示搜索缺省图
}
}).catch(() => {
this.loading = false // 接口返回错误也需要停止掉 loading 圈圈效果,然后弹出框提示用户出错
this.$message.warning('加载失败')
})
}
重点在于请求分页接口的两种情况。一种情况是整页的查询,你在下拉滚动到底部时请求接口获取下一页数据之后,数据是拼接在前一页数据后面的,所以要用 concat
方法拼接,如果直接赋值的话前一页数据就被覆盖了;另一种是你在输入时的实时查询,就要将页面数据先置空,重新赋值接口搜索出来的数据。
接着是实时输入时的搜索:
/** 搜索框中发生输入变化触发的函数方法
* @method searchChange
* @param {string} value 搜索框输入的字符
*/
searchChange(value) {
this.title = value // 将 title 赋值成你正在输入的字符
this.page = { // 重置分页参数
pageNumber: 1,
pageSize: 8
}
// 滚动条回到顶部,因为这时候你可能有滚动前面的数据到某一个位置
if (this.ifDataEmpty !== true) {
document.getElementById('followData').scrollTop = 0
}
this.getData('2') // type 为2时为搜索查询,将页面数据置空,重新赋值成接口返回的数据
}
最后,记得及时销毁之前绑定的滚动事件:
destroyed() {
// 离开该界面后取消监听滚动
const el = document.getElementById('followData')
el && el.removeEventListener('scroll', this.scrollHandler)
}
好了,这样子就完美实现了,该方法同样适用于移动端,你也可以用各种插件来实现这种下拉滚动加载的效果,本方法是原生方法来实现的,欢迎补充互相学习~