React通过redux缓存列表数据以及滑动位置,回退时恢复页面状态

栏目: 服务器 · 发布时间: 6年前

内容简介:在使用所以我们希望能做到,从二级页面回退至列表页面时,列表页面能保留之前的状态(数据和滚动条位置)。那么怎么实现呢?下面分享一下React通过

在使用 ReactReact-router 实现单页面应用时,会有这样一个场景:从列表页面点击某项条目进入详情页,然后回退至列表页面时,列表页面会重新刷新,不仅数据重新获取了,滚动条也回到了顶部。用户要继续查看剩余数据的话,需要重新滑动到之前点击的那个条目,如果列表做了分页的话就更麻烦了,这对于用户体验来说是非常不好的。

所以我们希望能做到,从二级页面回退至列表页面时,列表页面能保留之前的状态(数据和滚动条位置)。

那么怎么实现呢?下面分享一下React通过 redux 来缓存列表数据以及滑动位置,以达到保留列表页面状态的方法。

关于redux以及react-redux的使用,这里就不做讲解了,可以参考我之前写的 React-redux的原理以及使用 。当然网络上有很多讲解得更清晰的文章,读者可以自行搜索。

下面直接进入正题,介绍实现需求的步骤吧

1、安装redux以及react-redux

cnpm install redux react-redux -dev --save

2、编写操作列表页面相关数据的action

/**
 * Created by RaoMeng on 2018/12/10
 * Desc: 列表数据缓存
 */

import {CLEAR_LIST_STATE, LIST_STATE} from "../constants/actionTypes";
import store from '../store/store'

/**
 * 保存列表状态
 * @param data
 * @returns {Function}
 */
export const saveListState = (data) => {
    return () => {
        store.dispatch({
            type: LIST_STATE,
            ...data
        })
    }
}

/**
 * 清除列表状态
 * @returns {Function}
 */
export const clearListState = () => {
    return () => {
        store.dispatch({
            type: CLEAR_LIST_STATE
        })
    }
}

这里实现了两个actionType,一个是保存列表状态,一个是清除列表状态。

保存列表状态就是为了达到回退时不刷新页面的需求;

清除列表状态则是因为:从菜单页面进入列表页面时,是要求重新加载页面数据的,假如不清除redux中的缓存数据,页面就会读取缓存数据而不会重新请求网络数据,所以这个action也是很有必要的。

3、实现配合action操作state的reducer

import {CLEAR_LIST_STATE, LIST_STATE} from "../constants/actionTypes";

const initListState = {
    scrollTop: 0,//列表滑动位置
    listData: [],//列表数据
    pageIndex: 1,//当前分页页码
    itemIndex: -1,//点击的条目index
}

const redListState = (state = initListState, action) => {
    if (action === undefined) {
        return state
    }

    switch (action.type) {
        case LIST_STATE:
            //更新列表状态
            return {
                ...state,
                ...action
            }
        case CLEAR_LIST_STATE:
            //清空列表状态
            return initListState
        default:
            return state
    }

}

export default redListState
/**
 * Created by RaoMeng on 2018/12/10
 * Desc: 数据处理中心
 */

import {combineReducers} from 'redux'
import redUserInfo from './redUserInfo'
import redListState from './redListState'
import redClassData from './redClassData'

const reducers = combineReducers({redUserInfo, redListState, redClassData})

export default reducers

这里解释下为什么要记录 分页页码 以及 点击的条目index

记录分页页码只是在列表数据做了分页的情况下需要。是为了回退到列表页面后,用户继续上拉加载数据时页码是正确的。

记录点击的条目index则是为了能在详情页更新所点击的条目数据。比如说一个会议签到列表,用户点击某条数据进入详情页后,点击签到按钮,这时我们要根据 itemIndex 来调用action的 saveListState()() 方法更新缓存中相应的数据,将该条数据的状态改为已签到。这样回退至列表页面时,该条数据的展示才会正确。

4、创建store

import {createStore} from 'redux'
import reducers from '../reducers/index'
import {persistStore, persistReducer} from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';

const persistConfig = {
    key: 'root',
    storage: storage,
    stateReconciler: autoMergeLevel2 // 查看 'Merge Process' 部分的具体情况
};

const myPersistReducer = persistReducer(persistConfig, reducers)

const store = createStore(myPersistReducer)

export const persistor = persistStore(store)
export default store

这里用到了 redux-persist 来实现redux数据的持久化存储,我在 React通过redux-persist持久化数据存储 有做简单讲解。

5、在点击条目的回调事件中调用saveListState方法保存列表状态

<父布局
        ref={el => {
               this.container = el
        }}
        > </父布局>

    onItemClick = index => {
        console.log('scrollTop', ReactDOM.findDOMNode(this.container).scrollTop)
        saveListState({
            scrollTop: ReactDOM.findDOMNode(this.container).scrollTop,
            listData: this.state.meetingSignList,
            pageIndex: mPageIndex,
            itemIndex: index,
        })()

        const {meetingSignList} = this.state
        this.props.history.push('/meet-detail/' + meetingSignList[index].meetId)
    }

通过ReactDOM.findDOMNode(this.container).scrollTop来获取父布局的滑动距离

6、在页面的componentDidMount方法中获取redux数据

首先通过 react-redux 的connect方法将state中的数据绑定到页面的props中,方便访问

let mapStateToProps = (state) => ({
    listState: {...state.redListState}
})

let mapDispatchToProps = (dispatch) => ({})

export default connect(mapStateToProps, mapDispatchToProps)(MeetingSignIn)

这样,在页面中就可以通过this.props.listState来访问redux中缓存的列表数据了

然后,在componentDidMount中获取缓存的列表数据,如果有缓存数据,则加载,如果没有则重新请求

componentDidMount() {
        document.title = '会议管理'
        console.log('listState', this.props.listState)
        if (this.props.listState && !isObjEmpty(this.props.listState.listData)) {
            this.setState({
                meetingSignList: this.props.listState.listData,
                isLoading: false,
            }, () => {
                ReactDOM.findDOMNode(this.container).scrollTop = this.props.listState.scrollTop
            })
            mPageIndex = this.props.listState.pageIndex
        } else {
            Toast.loading('数据加载中...', 0)
            mPageIndex = 0
            this.loadMeetList()
        }
    }

这样就实现了React通过redux缓存列表数据以及滑动位置,回退时恢复页面状态的需求。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Python 3面向对象编程

Python 3面向对象编程

[加]Dusty Phillips(达斯帝•菲利普斯) / 肖鹏、常贺、石琳 / 电子工业出版社 / 2015-6 / 79.00元

Python 是一种面向对象的解释型语言,面向对象是其非常重要的特性。《Python 3面向对象编程》通过Python 的数据结构、语法、设计模式,从简单到复杂,从初级到高级,一步步通过例子来展示了Python 中面向对象的概念和原则。 《Python 3面向对象编程》不是Python 的入门书籍,适合具有Python 基础经验的开发人员阅读。如果你拥有其他面向对象语言的经验,你会更容易理解......一起来看看 《Python 3面向对象编程》 这本书的介绍吧!

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具