上一篇React項目實踐(二)一個登陸頁面的狀態遷移javascript
分析:咱們須要實現兩個方向(向下拉動,向上滑動)上的拉動刷新,考慮完成 PullDownRefresh 和 PullUpRefresh 兩個組件的編寫。思考其中細節:
① 自適應滾動的內容是基於頁面仍是基於內部容器;
② 組件是否能夠組合使用;
③ 狀態提示loading如何設計;
④ loading開始與結束的時機,定時器規定時間?數據加載完結束?css
目前實現:
① 暫時未考慮頁面和內部容器同時滑動的狀況;
② 經過 props.children
傳入須要拉動刷新的內容,兩個組件可組合使用;
③ 經過一個 refreshing
狀態變量來決定當前是否處於刷新狀態;
④ 經過在 componentWillReceiveProps
生命週期鉤子中接收新狀態/數據來控制 loading 的結束,即 refreshing=false
html
依舊是模仿掘金主頁的實現 java
弄清楚元素的幾個屬性值(翻一下MDN吧)react
offsetHeight 是一個DOM屬性。它有時被稱爲一個元素的物理/圖形的尺寸,或是一個元素的邊界框(border-box)的高度。 git
scrollTop 屬性能夠獲取或設置一個元素的內容垂直滾動的像素數。部到視口可見內容(的頂部)的距離的度量。當一個元素的內容沒有產生垂直方向的滾動條,那麼它的 scrollTop 值爲0 github
scrollHeight:這個只讀屬性是一個元素內容高度的度量,包括因爲溢出致使的視圖中不可見內容。(屬性將會對值四捨五入取整)。包括元素的padding,但不包括元素的border和margin。scrollHeight也包括 ::before
和 ::after
這樣的僞元素。 web
element.scrollHeight - element.scrollTop === element.clientHeight promise
getBoundingClientRect()
方法返回元素的大小及其相對於視口的位置。 瀏覽器
Window.scrollY:返回文檔在垂直方向已滾動的像素值。跨瀏覽器兼容:
var supportPageOffset = window.pageXOffset !== undefined;
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
var y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
複製代碼
Touch.pageY:觸點相對於HTML文檔上邊沿的的Y座標. 和 clientY 屬性不一樣, 這個值是相對於整個html文檔的座標, 和用戶滾動位置無關. 所以當存在垂直滾動的偏移時, 這個值包含了垂直滾動的偏移
首先要明確的是下拉刷新組件的觸發條件:① 內容垂直滾動的距離應該爲0;② 觸屏拉動的距離應該大於某個給定的閾值;③ 明確到底是哪一個容器設置了內容自動滾動。下面以我寫的具體例子做爲參考(沒有考慮複雜狀況)
overflow-y:auto
<div className="main scroll_content">
<PullDownRefresh onRefresh={this._onRefreshDown} refreshing={this.state.refreshing}> {entryList.map((element, index) => { return <EntryItem item={element} key={index} /> })} </PullDownRefresh> 複製代碼
<>
{this.state.refreshing ? <RefreshLoading orient="up" /> : null} <div ref={el => (this.scrollContent = el)} onTouchStart={this.handleTouchStart} onTouchMove={this.handleTouchMove} onTouchEnd={this.handleTouchEnd} > {this.props.children} </div> </> 複製代碼
handleTouchStart = e => {
this.setState({
startPos: e.touches[0].pageY
})
}
複製代碼
refreshing: true
)handleTouchMove = e => {
if (
this.state.refreshing === false &&
this.state.parentNode.scrollTop === 0
) {
let _pullHeight = e.touches[0].pageY - this.state.startPos
if (_pullHeight > this.state.minHeight) {
this.setState({
refreshing: true
})
}
}
}
複製代碼
handleTouchEnd = e => {
if (this.state.refreshing) {
this.props.onRefresh()
}
}
複製代碼
refreshing: false
);若是咱們是使用外部傳入的數據,須要在 componentWillReceiveProps 中設置更新結束(refreshing: false
)componentWillReceiveProps(nextProps) {
if (nextProps.refreshing !== this.state.refreshing) {
this.setState({
refreshing: nextProps.refreshing
})
}
}
複製代碼
var scrollContent = ReactDOM.findDOMNode(this.scrollContent).parentNode
複製代碼
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
var scrollContent = isCSS1Compat ? document.documentElement : document.body;
複製代碼
原理相似,不過多贅述,判斷到達底部的條件是:
scrollContent.scrollHeight - scrollContent.scrollTop - scrollContent.clientHeight === 0
複製代碼
咱們既想要滾動的功能,又不但願內部容器顯示滾動條,考慮爲內部容器添加類 scroll_content 實現
::-webkit-scrollbar {
/*隱藏滾輪*/
display: none;
}
.scroll_content {
-ms-scroll-chaining: chained;
-ms-overflow-style: none;
-ms-content-zooming: zoom;
-ms-scroll-rails: none;
-ms-content-zoom-limit-min: 100%;
-ms-content-zoom-limit-max: 500%;
-ms-scroll-snap-type: proximity;
-ms-scroll-snap-points-x: snapList(100%, 200%, 300%, 400%, 500%);
-ms-overflow-style: none;
overflow: auto;
-ms-overflow-style: none;
overflow: -moz-scrollbars-none;
}
複製代碼
--
總結:
① 一些功能仍待完善:好比,這裏下拉自動回彈使用了動畫,考慮釋放後再回彈;
② componentWillReceiveProps 是常常使用的一個生命週期鉤子,包括在參數路由改變時更新數據;