preface
In the daily development of H5, it is often encountered that the list is clicked to enter details and then returned to the list. Different from APP, APP is a layer upon layer of View covered with LastPage, which can naturally save the state of the LastPage. However, unlike H5, all the states returned from details to the list will be cleared. Walking through the lifecycle again, if the list is long, clicking on details and then going back to the top of the list can be very frustrating to the user experience, so list caching is a must, followed by CacheHoc implementation.
thinking
Caching caching is basically two things: when a page leaves, and when it reenters, it retrieves data. When and where? When and where to get it?
When to deposit
This problem is very simple, of course, is the page is about to destroy the time to save, also known as componentWillUnmount life cycle to save operation.
Where there is
- If the data is persistent, it can be saved to
url
或localStorage
In whichurl
You can firstpass
Drop, because in the case of a complex list, there’s a lot of data that needs to be stored, all of iturl
Will makeurl
Long, obviously not right,localStorage
It’s a way of providinggetItem
,setItem
The API is also sufficient to support access operations, up to 5M, the capacity is sufficient, and can also be serializedSerialize
Integration. - Memory, for lists or data that don’t need to be persisted, memory is probably a better way to do that, why is that, for example, if you go from list -> detail -> list you need to cache that’s fine, but if you go back to the home page and re-enter the list logically you shouldn’t be using cached data before, So we can put it in
redux
或rematch
State management tools, such as state management tools, encapsulate access methods, which are convenient, or put globallywindow
In the.
When to take
This problem is simple enough to fetch at page entry, but it is important to note that only fetch at POP, because every time we PUSH, we should enter a new page, and we should not use cached data in this case.
Where to take
—
CacheHoc
Cache scheme based on
CacheHoc is a higher-order component where cached data is stored in a window. We simply pass in CACHE_NAME, scrollElRefs. CACHE_NAME is the key used to cache data. ScrollElRefs is an array containing scrollElRefs, which is used to record the scrollTop and state of the corresponding scrollElRefs in the life cycle function componentWillUnmount. Initialize State in Constructor and update scrollTop in componentDidMount.
Simple to use
import React from 'react'
import { connect } from 'react-redux'
import cacheHoc from 'utils/cache_hoc'
@connect(mapStateToProps, mapDispatch)
@cacheHoc export default class extends React.Component { constructor (. props) { super(... props) this.props.withRef(this) } / / set CACVHE_NAME CACHE_NAME = `customerListThe ${this.props.index}`; scrollDom = null state = { orderBy: '2'. loading: false. num: 1. dataSource: [], keyWord: undefined } componentDidMount () { // Set the scroll container list this.scrollElRefs = [this.scrollDom] // Request data to update state } render () { const { history } = this.props const { dataSource, orderBy, loading } = this.state return ( <div className={gcmc('wrapper')} > <MeScroll className={gcmc('wrapper')} getMs={ref= > (this.scrollDom = ref)} loadMore={this.fetchData} refresh={this.refresh} up={{ page: { num: 1.// The current page number, which defaults to 0, will be incremented by 1 before the callback, i.e. callback(page) will start at 1 size: 15 // The amount of data per page // time: null // The first page of data server return time; Prevent the user to turn the page, the background added data, resulting in the next page data duplication; } }} down={{ auto: false }} > {loading ? ( <div className={gcmc('loading-wrapper')} > <Loading /> </div> ) : ( dataSource.map(item => ( <Card key={item.clienteleId} data={item} {... this.props} onClick={() => history.push('/detail/id') } /> )) )} </MeScroll> <div className={styles['sort']} > <div className={styles['sort-wrapper']} onClick={this._toSort}> <span style={{marginRight: 3}}> </span> <img src={orderBy === '2'? SORT_UP : SORT_DOWN} alt='sort' style={{ width: 10, height: 16 }} /> </div> </div> </div> ) } } Copy the code
The effect is as follows:
Cached data:
code
const storeName = 'CACHE_STORAGE'
window[storeName] = {}
export default Comp => {
return class CacheWrapper extends Comp {
constructor (props) { super(props) if (!window[storeName][this.CACHE_NAME]) { // Initializes the cache key according to CACHE_NAME window[storeName][this.CACHE_NAME] = {} } // Used to store information such as state this.store = window[storeName][this.CACHE_NAME] const { history: { action } = {} } = props // State is initialized only if a value is returned in &state if (action === 'POP') { const { state } = this.store if (state) { this.state = state } } else { // When you enter the list again, i.e. from the home page, clear the last cached information window[storeName][this.CACHE_NAME] = {} this.store = window[storeName][this.CACHE_NAME] } } async componentDidMount () { if (super.componentDidMount) { await super.componentDidMount() } const { history: { action } = {} } = this.props if(action ! = ='POP') return const { scrollTops = [] } = this.store const { scrollElRefs = [] } = this scrollElRefs.forEach((el, index) = > { if(el && el.scrollTop ! = =undefined) { el.scrollTop = scrollTops[index] } }) } componentWillUnmount () { if (super.componentWillUnmount) { super.componentWillUnmount() } this.store.state = this.state const scrollTops = [] const { scrollElRefs = [] } = this scrollElRefs.forEach(ref= > { if(ref && ref.scrollTop ! = =undefined) { scrollTops.push(ref.scrollTop) } }) this.store.scrollTops = scrollTops } } } Copy the code
conclusion
In fact, the way of caching are similar, on the above points, the specific scheme to be used according to the actual application scenarios to choose, it is important to analyze the timing and location of access, the realization is just to write out the logic in the brain.
This article is formatted using MDNICE