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

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

内容简介:在使用所以我们希望能做到,从二级页面回退至列表页面时,列表页面能保留之前的状态(数据和滚动条位置)。那么怎么实现呢?下面分享一下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缓存列表数据以及滑动位置,回退时恢复页面状态的需求。


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

查看所有标签

猜你喜欢:

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

计算机组成(第 6 版)

计算机组成(第 6 版)

Andrew S. Tanenbaum、Todd Austin / 刘卫东、宋佳兴 / 机械工业出版社 / 2014-8-19 / CNY 99.00

本书采用结构化方法来介绍计算机系统,书的内容完全建立在“计算机是由层次结构组成的,每层完成规定的功能”这一概念之上。作者对本版进行了彻底的更新,以反映当今最重要的计算机技术以及计算机组成和体系结构方面的最新进展。书中详细讨论了数字逻辑层、微体系结构层、指令系统层、操作系统层和汇编语言层,并涵盖了并行体系结构的内容,而且每一章结尾都配有丰富的习题。本书适合作为计算机专业本科生计算机组成与结构课程的教......一起来看看 《计算机组成(第 6 版)》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码

SHA 加密
SHA 加密

SHA 加密工具