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、React-Hooks、Redux、TypeScript、Vite2、Ant-Design 开源的一套后台管理框架。
【资源说明】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的...基于react+react-router+redux+AntD+Echarts+es6+webpack的共享单车后台管理系统源码+项目说明.zip
搭建项目 ...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-cli说明React + React-Router + TS + JS +蚂蚁设计+ webpack4.0脚手架业务介绍目录结构├── dist // 编译结果目录├── build // webpack 配置目录│ ├── webpack.base.js // 公用配置│ ├─...
wx-react-app使用 + 框架整合,集合了react-redux、react-router-redux、redux-saga、axios 等。重要说明为什么不使用 Ant Design 官方的构建工具进行构建?由于官方构建工具,在 Debug 的时候,无法在源码上进行...
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...
包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。 包括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...
包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。 包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python...
使用react-router-dom、redux、redux-react技术,并对源码分析,手动实现; 涉及登录拦截,路由传参,http服务搭建 安装教程 打开git 运行 git clone 或点击下载ZIP后解压 使用说明 cd 项目目录 npm install npm run ...
react4 + react-redux + react-router + es6 + axios + sass + webpack 说明 觉得对你有帮助,请点右上角的Star支持一下 bailicangdu大神的项目地址 推荐一下我的另一个项目“用console.log看vue源码” 项目运行 node...
java开发oa办公系统源码 oa办公系统 前端使用webpack,react,ant desidn,react-redux开发, 后端同事提供,环境是tomcat7.x,开发语言java,目录结构: 资源文件:ROOT/resouces/.js | .css 页面:ROOT/WEB-INF/page...
包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。 包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python...
包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。 包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python...
我们接下来主要从 React 的使用方式、源码层面和周边生态(如 redux, react-router 等)等几个方便来进行总结。 1. 使用方式上 这里主要考察的是,在开发使用过程中,对 React 框架的了解,如 hook 的不同调用方式...