今天在渲染一个页面列表的问题,数据是从后台返回的,但是一开始只是加载一部分的数据(后台有page字段,表示返回第几页数据),当我在第一页向下滚动页面滚动到当前页数据的底部的时候(也就是滚动到浏览器的底部),才去请求第2页的数据。
使用vue写的页面,axios发送请求。
1、关于get和post请求
前面一段时间一直是在本地模拟数据写页面,导致很长一段时间没有使用ajax请求,居然忘了get请求传递数据就是通过url地址来传递的。罪过罪过。。。
比如: let url = '/api?param=' + data,那么param就是传给后台的数据参数。
而post是放在请求的字段中的。
好比货车运输东西,get请求就相当于是放在车顶的货物,post是放在车内的货物,所以相对来说post较为安全,所以一般get请求不传递敏感数据,敏感数据一般用post请求传。
2、如何判断页面数据到达浏览器的底部?
这里我们使用浏览器的三个高度值:
浏览器窗口(文档)的可视高度(visionHeight):(就是你肉眼可见的那部分全屏高度)
window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
浏览器向上滚动的高度(scrolledHeight):
window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
文档的真实高度(trueHeight):
document.documentElement.scrollHeight || document.body.scrollHeight
所以: visionHeight + scrolledHeight = trueHeight 就表示滚到底了。
3、假设当前页是第1页,现在需要滚动,顺序加载第2页、第3页的数据
3.1 设定一个page值,来表示加载第几页的内容,默认是1 (page = 1)
3.2 使用get请求,就直接在url后面拼接page参数(比如 let url = /api/orders?type=1&page=1)
因为页面上有tab,所以type表示第几个tab,默认等于1(type = 1,也就是tab的index + 1)
页面是这样的
3.3 页面初始化的时候,给window绑定scroll事件,事件处理函数是isBottomFun
`window.addEventListener('scroll', this.isBottomFun)`
3.4 事件处理函数内容
3.4.1 首先获取上面所说的三个高度`visionHeight`、`scrolledHeight`、`trueHeight`
3.4.2 然后,当我滚动到底部,且超出了底部高度的时候,就发送请求,请求第2页的数据。也就是
if (scrolledHeight >= trueHeight - visionHeight){
this.page++;
//lockFlag初始值为true,用来锁定请求
if (this.lockFlag && this.page <= this.totalPage) {
this.lockFlag = false //上一个请求没有成功返回时,不允许再进行下一个请求
let url = 'http://m.youxiake.local/api/orders?type=' + this.type + '&page=' + this.page
// let url = '/api/orders' + this.type + '&page=' + this.page
if (this.cache[url]) {
this.showLoading = false
this.orderLists = this.orderLists.concat(this.cache[url])
} else {
this.showLoading = true
axios.get(url).then((data) => {
this.showLoading = false
let _data = data.data.data
this.cache[url] = _data.orderList
this.orderLists = this.orderLists.concat(_data.orderList)
this.lockFlag = true //请求成功,可以进行下一个请求循环
})
}
}
}
3.4.3 当用户点击页面上的tab的时候,如果用户点击了tab2,瞬间又点击了tab3,这样导致tab2页面的数据还没返回,又开
始请求tab3的数据,但是用户只想看到最后点击的页面的数据,这就需要取消请求。
也就是,在用户点击tab3的时候,如果tab2的数据还没有返回,就取消这个请求。
axios里面有一个`axios.CancelToken.source().token`方法来获取一个token以及`axios.CancelToken.source().cancel()`
方法来取消请求
`let XHRAbort = axios.CancelToken.source()`
如果XHRAbort有值,就取消请求(XHRAbort.cancel()),否则就把token传给后端
if (this.XHRAbort) {
this.XHRAbort.cancel()
}
this.XHRAbort = axios.CancelToken.source()
this.showLoading = true
axios.get(url, {
cancelToken: this.XHRAbort.token
}).then((data) => {
console.log(data)
})
3.4.4 请求缓存
也就是,点击过的tab已经请求过了,就不要重新去请求数据了,这里使用一个对象来存,把url作为它的key
cache[url] = data
如果cache[url]有值,就不发请求,直接使用。
//以下更新于2018/08/09
3.4.5 缓存的数据
上面缓存的只是我需要的数组,但是如果我还需要其他的数据,就需要存储一个对象,将其他数组缓存起来。
cache[url] = {
list: cacheTemp,
totalPage: res.data.data.data.last_page,
}
3.4.6 已缓存的数据加载太快
这个现象其实不是数据加载太快,而是解锁的时间或时机不对。
应该在设置完数据字段之后再解锁。如果还是过快,就加个时间延迟。