npm install [email protected] -S
v5文档:React Router: Declarative Routing for React.js
React路由的编程特点:组件化、hooks api、withRouter。
安装react-router-dom(v5.3.0),会使用HashRouter、Route、Switch、Redirect、Link。
使用@loadable/component(React.lazy、Suspense)实现“代码分割”。
安装antd-mobile,把tabbar组件搞进来。
在react-router-dom路由系统中,不是每个React组件都能访问到路由api。只有那些被Route直接包裹过的React页面组件可以通过props访问到路由api。
那些未被Route直接包裹的React组件默认无法访问路由api,怎么办呢?
可以通过属性继承{...props}语法,把页面组件的props(路由API)手动向后代组件传递。
使用withRouter这个高阶组件,向组件中注入路由API。(非Hooks编程中用得比较多)
使用react-router-dom(v5)提供的hooks api直接使用路由API。
修改react-router-dom出口,把路由上下文对象抛出来,useContext()直接使用这些路由API。
路由传参:params动态路由传参,query传参。
嵌套视图:Route所包裹的组件中又使用了Route。
在嵌套视图时,一定要用Switch把二级Route路由包裹起来。
在编写Route规则,不要“一刀切地加exact”,注意exact对 / 的影响。
function App() {
return (
)
}
function List() {
return (
)
}
在v6中如何解决“嵌套视图”的问题(v6中用element渲染组件)
}>
}>
}>
}>
function Find() {
return (
something
)
}
可以使用React.lazy 和 React Router 这类的第三方库,来配置基于路由的代码分割,实现按需加载。
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const App = () => (
Loading...
但由于React.lazy 和 Suspense 技术还不支持服务端渲染,所以React给我们推荐了 @loadable/component 代码示例:
import loadable from '@loadable/component'
const OtherComponent = loadable(() => import('./OtherComponent'))
function MyComponent() {
return (
)
}
注意:使用上面的库我们需要在babel文件中引入这两个插件(plugins)
{
"presets": ["@babel/preset-react"],
"plugins": ["@babel/plugin-syntax-dynamic-import"]
}
import React from 'react'; import {Route,Redirect,Switch,BrowserRouter,useHistory} from 'react-router-dom'; import T from './views/T' //导入要跳转的React页面 const B=()=>{ const hist = useHistory() return (
{ hist.push(`/res/1fejwdhla`) }}> 页面跳转) } function App() { return ( <>> ); } export default App; {/* 当路径为/时显示 */} {/* 使用 :id 可以将路由后面的参数以id的参数值传递到res路由的页面 */} {/* 当之前的路由都不满足时,重定向为根页面 */} import React from 'react'; export default (props => { console.log(props) return (
) }) 这是T页面
我们可以通过props可以查看到上一个页面传过来的携带过来路由信息。
monbx(V6) + mobx-react(v7)
- 安装mobx(v6),用面向对象语法编写store和子store的代码逻辑。
- 安装mobx-react(v7),在APP根组件中,使用
- 在React组件中,使用inject('user')(observer(props=>()))
安装:
npm i mobx mobx-react -S
根store的入口文件
//创建一个store文件 import UserStore from "./user"; class Store { constructor(){ this.user= new UserStore() this.dd=789456 } dd=456 } export default new Store()
子store 文件
import { makeAutoObservable, observable, action, flow } from 'mobx' import { fetchArticleList } from '../api' export default class UserStore { constructor() { //makeAutoObservable自动转换该类中的属性和方法 // makeAutoObservable(target, annotations?, options?) // target:指定要转化的目标实例对象 一般都指向当前Clas // annotations: 注解对象 // key:指定要转化的属性或方法 // value:annotation(注解,从 mobx 引入的方法),指定要转换成什么 // 所有 自有 属性都成为 observable。 // 所有 getters 都成为 computed。 // 所有 setters 都成为 action。 // 所有 prototype 中的 functions 都成为 autoAction。 // 所有 prototype 中的 generator functions 都成为 flow。(需要注意,generators 函数在某些编译器配置中无法被检测到,如果 flow 没有正常运行,请务必明确地指定 flow 注解。) // 即:把当前对象上的成员属性变成observable变量,把成员方法变成action方法。 makeAutoObservable(this, { token: observable, list: observable, num: observable, num2: computed, changeNum: action, //当在action中需要用到同步的async/await时,建议使用 flow,编写generator的语法。 getList: flow }) } token = 'token' list = [] num = 1 get num2() { return this.num * 100 } changeNum(payload) { this.num += payload } * getList(params) { const list = yield fetchArticleList(params) //此处是发送请求获取返回列表的示例 this.list = list } }
注意:我们要在jsx页面文件中获取到store数据,我们需要使用Provider提供store数据
// 引入mobx状态管理 import { Provider } from 'mobx-react'; import store from './store'; ...
{/* 这里为需要store数据的jsx组件页面 */} ...react T.jsx页面
import React from 'react'; import { inject , observer} from 'mobx-react' // 注意: 要先观察再注入即 inject(observer(...)) // 'user','dd' 为要从store注入的数据 export default inject('user','dd')( // observer(UI) 把当前组件变成观察者,当store数据发生变化时,组件将会自动更新 observer( ({user,dd}) => { console.log(user,dd) return (
) } ) ) 这是T页面
{user.num}{/* 调用userstore中的action方法 */}