1. 写在前面
我最开始纠结当用户滑动时onTouchMove事件会不停的执行去调接口,于是我侥幸的想只用onTouchEnd事件去判断用户是否滑到最底部,但是这种方法应用到项目中才发现点击的时候也会触发onTouchEnd,实际应用并不理想。
光判断滑到最底部是不够的,首先需要知道用户现在的操作,是点击还是滑动(向上、向下、向左、向右),这里受到了[原生js判断手指滑动方向][1]的启发。
2. demo
class demo Component { constructor(props) { super(props); this.state = { finished: false,//是否全部加载完毕 isFoot: true, //阻止用户频繁上拉调接口 } this._page = 1; //分页页码 this.val = ''; //搜索框的值 this._page_size = 5; //每页显示个数 this.startx; //触摸起始点x轴坐标 this.starty; //触摸起始点y轴坐标 } //接触屏幕 touchStart(e) { this.startx = e.touches[0].pageX; this.starty = e.touches[0].pageY; } //离开屏幕([e.changedTouches][2]) touchEnd(e) { let endx, endy; endx = e.changedTouches[0].pageX; endy = e.changedTouches[0].pageY; let direction = this.getDirection(this.startx, this.starty, endx, endy); switch (direction) { case 0: console.log("未滑动!"); break; case 1: console.log("向上!"); this.loadData(); break; case 2: console.log("向下!"); break; case 3: console.log("向左!"); break; case 4: console.log("向右!"); break; default: } } //触摸点和离开点连线与[x轴角度][3] getAngle(angx,angy) { return Math.atan2(angy, angx) * 180 / Math.PI; } //根据接触和离开判断方向 1向上 2向下 3向左 4向右 0未发生滑动([Math.abs][4]) getDirection(startx, starty, endx, endy) { let angx = endx - startx; let angy = endy - starty; let result = 0; //如果滑动距离太短 if (Math.abs(angx) < 2 && Math.abs(angy) < 2) { return result; } let angle = this.getAngle(angx, angy); if (angle >= -135 && angle <= -45) { result = 1; } else if (angle > 45 && angle < 135) { result = 2; } else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) { result = 3; } else if (angle >= -45 && angle <= 45) { result = 4; } return result; } //**向上滑动时(在这里才真正的判断是否到最底部)** loadData() { console.log("数据的高-------------------------", this.refs.onPullUp.clientHeight); console.log("滚动的高------------------------", document.documentElement.scrollTop); console.log("滚动的高------------------------", document.body.scrollTop); console.log("屏幕的高------------------------", document.documentElement.clientHeight); let { meActs } = this.props; let dataHeight = this.refs.onPullUp.clientHeight; let scrollHeight = document.body.scrollTop || document.documentElement.scrollTop; let screenHeight = document.documentElement.clientHeight; const h = 10;//自定义距离底部多少时concat数据 if (dataHeight - scrollHeight - h < screenHeight && this.state.isFoot) { this.setState({ isFoot: false, }); console.log("应该只显示1次"); let params = { value: this.val, page_index: this._page, page_size: this._page_size, } meActs.getRecentReadList(this.accessKey, this.accessID, params).then((res) => { if (res.data.code === 10000 && res.data.data.list.length > 0) { this.setState({ isFoot: true, }); this._page++; } //数据加载完毕 if (res.data.code === 10000 && res.data.data.list.length == 0) { this.setState({ finished: true, }) } }); } } render() { return() }} {listItems}{ this.state.finished ? 我是有底线的 : recentReadList.list.length > 0 ? this.state.isFoot ? 上拉加载更多 :: 暂无信息 }
3. 兼容性
微信端ios 安卓暂时还未发现任何异常(已上线的项目)
4. 结语
移动端触摸事件的用处远不止如此,这次是因为antd自带的上拉加载插件在自身项目中应用太复杂所以决定自己写一个满足自身项目需求的代码少兼容性还看得过去的就行。最近想找react图片缩放的插件,感觉也跟触摸事件有关,可以研究一下。
**