1. 程式人生 > >React-實現上拉載入更多

React-實現上拉載入更多

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( <div className='recentRead paddingTop90' ref="onPullUp"> <TitleBar title="歷史閱讀" onClickBack={this.onClickBack.bind(this)} /> <SearchBar onSubmit={this.onSearch.bind(this)} onCancel={this.onSearchCancel.bind(this)} placeholder='搜尋' ref="searchBar" /> <div className="touch-box" onTouchStart={this.touchStart.bind(this)} onTouchEnd={this.touchEnd.bind(this)}> {listItems} </div> <div className="common-bottomTotal"> { this.state.finished ? <span>我是有底線的</span> : recentReadList.list.length > 0 ? this.state.isFoot ? <span >上拉載入更多</span> : <ActivityIndicator text="請稍等..." /> : <span className='iconfont icon-taidu2'>暫無資訊</span> } </div> </div> ) } }

3. 相容性

微信端ios 安卓暫時還未發現任何異常(已上線的專案) 

4. 結語

移動端觸控事件的用處遠不止如此,這次是因為antd自帶的上拉載入外掛在自身專案中應用太複雜所以決定自己
寫一個滿足自身專案需求的程式碼少相容性還看得過去的就行。最近想找react圖片縮放的外掛,感覺也跟觸控事件
有關,可以研究一下。

**