1.index.js
// 作为外部syncHistoryWithStore接口方法 // 绑定store.dispatch方法引起的state中路由状态变更到影响浏览器location变更 // 绑定浏览器location变更触发store.dispatch,更新state中路由状态 // 返回当前的histroy、绑定方法listen(dispatch方法触发时执行,以绑定前的路由状态为参数)、解绑函数unsubscribe export syncHistoryWithStore from './sync' // routerReducer监听路由变更子reducer,通过redux的combineReducers复合多个reducer后使用 export { LOCATION_CHANGE, routerReducer } from './reducer' // 构建actionCreater,作为外部push、replace、go、goBack、goForward方法的接口,通常不直接使用 export { CALL_HISTORY_METHOD, push, replace, go, goBack, goForward, routerActions } from './actions' // 构建route中间件,用于分发action,触发路径跳转等事件 // import {applyMiddleware, compose, createStore} from 'redux' // import {routerMiddleware} from 'react-router-redux' // import thunk from 'redux-thunk' // createStore(reducer,initialState, // compose( applyMiddleware([thunk, routerMiddleware(history)]) ) // ); export routerMiddleware from './middleware'
2.middleware.js
import { CALL_HISTORY_METHOD } from './actions' // 构建route中间件,用于分发action,触发路径跳转等事件,作为外部的routerMiddleware接口 // 使用方式为 // import {applyMiddleware, compose, createStore} from 'redux' // import {routerMiddleware} from 'react-router-redux' // import thunk from 'redux-thunk' // createStore(reducer,initialState, // compose( applyMiddleware([thunk, routerMiddleware(history)]) ) // ); // // history可以是客户端hashHistroy(url散列变化),服务器端boswerHistroy(路径、查询参数变化) // 通过hashHistroy、boswerHistroy触发期望的事件,即hashHistroy、boswerHistroy方法执行 // method是hashHistroy、boswerHistroy的接口方法,包含push、replace、go、goBack、goForward方法 // 问题:hashHistroy、boswerHistroy不使用redux.store.dispatch方法触发事件,是否会影响state??? // redux-logger插件需要在react-router-redux插件挂载前挂载,方能打印action??? export default function routerMiddleware(history) { return () => next => action => { if (action.type !== CALL_HISTORY_METHOD) { return next(action) } const { payload: { method, args } } = action history[method](...args) } }
3.reducer.js
export const LOCATION_CHANGE = '@@router/LOCATION_CHANGE' const initialState = { locationBeforeTransitions: null } // 监听路由变更子reducer,通过redux的combineReducers复合多个reducer后使用,作为外部routerReducer接口 // 提示redux使用过程中,可通过子组件模块中注入reducer,再使用combineReducers复合多个reducer // 最后使用replaceReducer方法更新当前store的reducer,意义是构建reducer拆解到各个子模块中 export function routerReducer(state = initialState, { type, payload } = {}) { if (type === LOCATION_CHANGE) { return { ...state, locationBeforeTransitions: payload } } return state }
4.actions.js
export const CALL_HISTORY_METHOD = '@@router/CALL_HISTORY_METHOD' function updateLocation(method) { return (...args) => ({// 返回actionCreater type: CALL_HISTORY_METHOD,// route事件标识,避免和用于定义的action冲突 payload: { method, args }// method系hashHistroy、boswerHistroy对外接口方法名,args为参数 }) } // 返回actionCreater,作为外部push、replace、go、goBack、goForward方法的接口,通常不直接使用 export const push = updateLocation('push') export const replace = updateLocation('replace') export const go = updateLocation('go') export const goBack = updateLocation('goBack') export const goForward = updateLocation('goForward') export const routerActions = { push, replace, go, goBack, goForward }
5.sync.js
import { LOCATION_CHANGE } from './reducer' // 默认state.routing存取route变更状态数据 const defaultSelectLocationState = state => state.routing // 作为外部syncHistoryWithStore接口方法 // 绑定store.dispatch方法引起的state中路由状态变更到影响浏览器location变更 // 绑定浏览器location变更触发store.dispatch,更新state中路由状态 // 返回当前的histroy、绑定方法listen(dispatch方法触发时执行,以绑定前的路由状态为参数)、解绑函数unsubscribe export default function syncHistoryWithStore(history, store, { // 约定redux.store.state中哪个属性用于存取route变更状态数据 selectLocationState = defaultSelectLocationState, // store中路由状态变更是否引起浏览器location改变 adjustUrlOnReplay = true } = {}) { // 确保redux.store.state中某个属性绑定了route变更状态 if (typeof selectLocationState(store.getState()) === 'undefined') { throw new Error( 'Expected the routing state to be available either as `state.routing` ' + 'or as the custom expression you can specify as `selectLocationState` ' + 'in the `syncHistoryWithStore()` options. ' + 'Ensure you have added the `routerReducer` to your store\'s ' + 'reducers via `combineReducers` or whatever method you use to isolate ' + 'your reducers.' ) } let initialLocation// 初始化route状态数据 let isTimeTraveling// 浏览器页面location.url改变过程中标识,区别页面链接及react-router-redux变更location两种情况 let unsubscribeFromStore// 移除store.listeners中,因路由状态引起浏览器location变更函数 let unsubscribeFromHistory// 移除location变更引起路由状态更新函数 let currentLocation// 记录上一个当前路由状态数据 // 获取路由事件触发后路由状态,或者useInitialIfEmpty为真值获取初始化route状态,或者undefined const getLocationInStore = (useInitialIfEmpty) => { const locationState = selectLocationState(store.getState()) // locationState.locationBeforeTransitions为真值时,跳转路由事件未发生 return locationState.locationBeforeTransitions || (useInitialIfEmpty ? initialLocation : undefined) } // 初始化route状态数据 initialLocation = getLocationInStore() // adjustUrlOnReplay为真值时,store数据改变事件dispatch发生后,浏览器页面更新location??? if (adjustUrlOnReplay) { // 由store中路由状态改变情况,更新浏览器location const handleStoreChange = () => { // 获取路由事件触发后路由状态,或者初始路由状态 const locationInStore = getLocationInStore(true) if (currentLocation === locationInStore || initialLocation === locationInStore) { return } // 浏览器页面location.url改变过程中标识,区别页面链接及react-router-redux变更location两种情况 isTimeTraveling = true // 记录上一个当前路由状态数据 currentLocation = locationInStore // store数据改变后,浏览器页面更新location??? history.transitionTo({ ...locationInStore, action: 'PUSH' }) isTimeTraveling = false } // 绑定事件,完成功能为,dispatch方法触发store中路由状态改变时,更新浏览器location unsubscribeFromStore = store.subscribe(handleStoreChange) // 初始化设置路由状态时引起页面location改变 handleStoreChange() } // 页面链接变更浏览器location,触发store.dispatch变更store中路由状态 const handleLocationChange = (location) => { // react-router-redux引起浏览器location变更过程中,无效;页面链接变更,有效 if (isTimeTraveling) { return } currentLocation = location if (!initialLocation) { initialLocation = location if (getLocationInStore()) { return } } store.dispatch({ type: LOCATION_CHANGE, payload: location }) } // hashHistory、boswerHistory监听浏览器location变更,触发store.dispatch变更store中路由状态 unsubscribeFromHistory = history.listen(handleLocationChange) // support history 3.x // 初始化更新store中路由状态 if(history.getCurrentLocation) { handleLocationChange(history.getCurrentLocation()) } // The enhanced history uses store as source of truth return { ...history, // store中dispatch方法触发时,绑定执行函数listener,以绑定前的路由状态为参数 listen(listener) { // 绑定前的路由状态 let lastPublishedLocation = getLocationInStore(true) let unsubscribed = false// 确保listener在解绑后不执行 const unsubscribeFromStore = store.subscribe(() => { const currentLocation = getLocationInStore(true) if (currentLocation === lastPublishedLocation) { return } lastPublishedLocation = currentLocation if (!unsubscribed) { listener(lastPublishedLocation) } }) listener(lastPublishedLocation) return () => { unsubscribed = true unsubscribeFromStore() } }, // 解绑函数,包括location到store的handleLocationChange、store到location的handleStoreChange unsubscribe() { if (adjustUrlOnReplay) { unsubscribeFromStore() } unsubscribeFromHistory() } } }
相关推荐
Hooks Admin 是一个全面的后台管理框架,它充分利用了React18、React-Router V6、Redux、React Hooks、TypeScript以及Vite2等现代前端技术,同时采用了流行的Ant Design UI库,为开发者提供了高效且易用的开发环境。...
【资源说明】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的...基于react+react-router+redux+AntD+Echarts+es6+webpack的共享单车后台管理系统源码+项目说明.zip
"仿小米有品React_React-redux_React-Router_Hooks.zip"这个项目,显然是一个基于React的实战项目,旨在模仿小米有品的电商平台,同时集成了React-redux、React-Router和React Hooks这三大关键组件,以实现更高效、...
搭建项目 ...3) redux+react-redux+redux-thunk 管理应用组件状态4) 学会使用 antd-mobile 组件库构建界面 5) mongoose 操作 mongodb 数据库 6) express 搭建后台路由 7) socket.io 实现实时通信 8) blue
├─1116_PM_React-basic-router-1.mp4 ├─1116_PM_React-basic-router-2.mp4 ├─1117_AM_React-basic-immutable-1.mp4 ├─1117_AM_React-basic-动画.mp4 ├─1117_PM_React-basic-immutable-2.mp4 ├─1117_PM_...
基于react+redux+react-router+webpack+es6+axios的仿QQ音乐客户端项目,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~ 项目简介: 技术栈 react react-router ...
【资源说明】 1、该资源内项目代码都是经过测试运行成功,功能正常的情况下才上传的,请放心下载使用。...基于react+react-router+redux+AntD+Echarts+es6+webpack的共享单车后台管理系统源码+项目说明.zip
这个脚手架结合了React、Redux、React-Router和Webpack等关键技术,帮助开发者快速搭建一个现代JavaScript应用的基础框架。 React是Facebook推出的一个用于构建用户界面的JavaScript库,特别是用于构建单页应用...
毕业设计的前台页面,项目做了前后端分离,需要后台提供json数据 ,旅游旅游网站,基于webpack,react,react-router,redux. 包含前端页面和/admin路由的后端页面 - 不懂运行,下载完可以私聊问,可远程教学 该资源内...
项目react-redux-cli说明React + React-Router + TS + JS +蚂蚁设计+ webpack4.0脚手架业务介绍目录结构├── dist // 编译结果目录├── build // webpack 配置目录│ ├── webpack.base.js // 公用配置│ ├─...
React Router是React生态中的路由库,负责管理应用的导航和页面间跳转。它允许开发者根据URL定义应用的路由结构,实现页面间的无刷新切换,提升用户体验。 Redux是状态管理库,它提供了一个中心化的store来存储应用...
wx-react-app使用 + 框架整合,集合了react-redux、react-router-redux、redux-saga、axios 等。重要说明为什么不使用 Ant Design 官方的构建工具进行构建?由于官方构建工具,在 Debug 的时候,无法在源码上进行...
在本文中,我们将深入探讨 React Router v4.0 的使用方法和源码解析。 首先,为了使用 React Router v4.0,我们需要安装 `react-router-dom` 包。这可以通过运行 `yarn add react-router-dom@next` 命令完成。`...
《React、Redux与React-Router-Dom深度解析》 在前端开发领域,React、Redux以及React-Router-Dom是三个非常重要的库,它们共同构建了现代JavaScript应用的基础架构。"react-redux-routerdom-master"这个项目可能是...
3) redux+react-redux+redux-thunk 管理应用组件状态4) 学会使用 antd-mobile 组件库构建界面 5) mongoose 操作 mongodb 数据库 6) express 搭建后台路由 7) socket.io 实现实时通信 8) blueimp-md5 对密码进行 MD5 ...
包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。 包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python...
基于react+redux+react-router+webpack+es6+axios的仿QQ音乐客户端项目 - 不懂运行,下载完可以私聊问,可远程教学 该资源内项目源码是个人的毕设,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分...
包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。 包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python...
react-router@4.3.1 redux@4+ 从webpack开始 思考一下webpack到底做了什么事情?其实简单来说,就是从入口文件开始,不断寻找依赖,同时为了解析各种不同的文件加载相应的loader,最后生成我们希望的类型的目标文件...
包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。 包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python...