安装
npm i react-router-dom --save
容器组件
- BrowserRouter 浏览器自带的H5 API, restful 风格,需要配合后台;
- HashRouter 使用 hash 方式进行路由,路径后均有#
- MemoryRouter 在内存中管理 history ,地址栏不会变化。在 reactNative 中使用。
路由的使用
- 跑通路由
//Home.js
import React,{Component}from 'react'
export default class Home extends Component{
render(){
return(
<div>
Home
</div>
)
}
}
//User.js
import React,{Component}from 'react'
export default class Home extends Component{
render(){
return(
<div>
User
</div>
)
}
}
//Profile.js
import React,{Component}from 'react'
export default class Home extends Component{
render(){
return(
<div>
Home
</div>
)
}
}
//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { HashRouter, Router, Route } from 'react-router-dom'
import Home from './components/Home'
import User from './components/User'
import Profile from './components/Profile'
ReactDOM.render(<HashRouter>
<div>
<Route path="/home" component={Home} />
<Route path="/profile" component={Profile} />
<Route path="/user" component={User} />
</div>
</HashRouter>, document.getElementById('root'));
- HashRouter 只能包含一个根元素 因此在所有的Route的外层包了一个div标签 尽量放在高的位置 比如主入口的index文件 是一个组件 直接加上<> 就可以使用 因为只有在HashRouter下面配置的Route路由才有用
- Route 组件有两个属性
- path
- component 当浏览器地址栏中的url和path匹配时会显示component属性对应的组件
路由匹配规则
- 若有一个组件 希望任何路由都显示时 把path的值设置为/
Link组件 是 react-router-dom的内置组件 起作用和VueRouter 和 router-link 类似 点击它可以跳转到指定路由
- 使用时需要导入 可以为其设置一个to属性 值就是单机这个Link时要跳转到路由的path(link 最后会被渲染成a标签展示出来)
- 因此在开发时尽量少些a 标签 因为路由不仅有 hash 模式还是 history 模式;写 Link 它会自动根据模式切换路径;
- 且to的值的这个路由path必须在Route 中注册过才行(只要在应用中注册过即可)
NavLink 和 Link 的作用一样,只不过当前导航激活时(NavLink 的 to 和页面 url 中的路径相同时导航被激活)会给当前被激活的 NavLink 添加一个 active 类名;如果设置 高亮当前激活的导航 给 active 类名添加样式就可以了
二级路由 类似VueRouter 的路由嵌套 直接在需要的地方定义Link 进行路由切换即可
动态路由和路由跳转
-动态路由的路径中有一段是不固定的,/user/detail/:id 这最后一段/:id就不是固定的,一般动态路由是用来页面间传数据的,动态路由也需要在Route中注册
这样写的是静态路由
<Route path='/user/detail' component={Home}></Route>
这样写的是动态路由,它与上面这个不是同一个路由,id是必须项
<Route path='/user/detail/:id' component={Home}></Route>
我们要跳转到动态路由的时候,后面的id可以直接拼接上去
<Link to={`/user/detail/${item.id}`}>
如果我们需要获取动态路由后面的动态部分,则使用props.match.params属性,值是一个对象,动态部分都被放在里面
componentWillMount,let { id } = this.props.match.params
编程式导航 用代码进行路由的切换
所有的被HashRouter等路由渲染的后代组件的props中都有一个路由信息对象history,其中有一个方法push就是用来切换路由的,参数接受一个路由path this.props.history.push('/home') //构造函数constructor中则是第一个参数props
路由匹配
路由匹配默认的是模糊匹配 开始匹配上了就匹配上了 多个路由匹配则多个component都会被渲染,很明显这不是我们想要的,那么就可以使用Route的exact关键字让该路由进行精确匹配,如下
<Route exact path='/home/list' component={list}></Route>
这样只有当路由是/home/list的时候才会渲染这个compoent,路由是/home时并不会渲染
render 属性 值是一个函数 这个函数要求返回一个jsx对象或者组件
当页面中的url的路径变化时与Route中的path向匹配时,就会执行这个render函数,然后将其返回的jsx或者组件渲染到页面上
Switch组件 使用时需导入 当Route匹配一个路由后就不在往后匹配 使用该组件
将所有的Route组件放进Switch组件中去,这样当有一个Route被匹配到后就不会再匹配其他的Route了
<Switch>
<Route path='/' exact render={() => <h1>首页</h1>}></Route>
<Route path='/home' component={Home}></Route>
<Route path='/login' component={Login}></Route>
<Route component={NotFound}></Route>
</Switch>
设置404 not found页面
只需要写一个没有path的Route就可以了,
<Route component={NotFound}></Route>
这样当出现匹配不到的路由就会渲染NotFound组件
create-reat-app创建的项目配置代理
在原来的 create-react-app 脚手架中,是通过 package.json 配置文件来配置代理的。但是,在新版的脚手架中,通过 package.json 只能配置一个代理。如果需要配置多个代理的话,则不能这么干了。
- 新版的代理配置,是通过 /src/setupProxy.js 这个文件来配置的。 在src下面新建文件setupProxy.js
/ 用来配置代理
const proxy = require('http-proxy-middleware')
module.exports = function(app) {
app.use(
proxy(
'/api', {
target: 'http://localhost:8888',
changeOrigin: true,
secure: false
}
)
)
}
配置完之后就可以了,会自动帮我们引用这个文件
受保护的路由 && 自定义菜单激活样式
在真实的项目中,我们会对一些路由进行保护机制,像有些页面用户没有登录则不允许访问。vueRouter中有导航守卫来处理这个问题,而在react-router中则需要写受保护的路由来实现 受保护的路由其实说白了就是我们自己实现一个组件来包裹Route组件,然后使用我们自己的组件替换掉Route组件,我们在我们自己的组件中做逻辑判断
import React, { Component } from 'react'
import { Route, Redirect } from 'react-router-dom'
export default ({component: Component, ...others}) => {
return <Route {...others} render={(props) => {
// props 是 router 对象,包含了当前路由的信息
return localStorage.getItem('loginSystem')
? <Component {...props} />
: <Redirect to={{pathname: '/login', from: props.match.url}} />
}
}></Route>
}
上面这就是一个受保护的组件,引用如下 import PrivateRoute from './components/Protected'
- 传一个path和component给我们写的保护组件(其实就是一个函数组件)中去,保护组件是一个函数组件,我们传的to以及component都会传进这个函数组件的第一个参数对象中去,我们直接将其解构然后给component重命名Component(组件首字母大写为了有别于原生标签),拿到component以及其他的to等props放进others对象中,然后保护组件返回一个Route组件,将to等props展开放进Route中,然后为Route设置一个render属性,render是一个方法,参数是router对象,包含了当前路由的信息,我们在render中做逻辑判断用户是否登录然后来渲染不同的组件(render函数需要返回一个jsx对象或者组件,然后在页面的url匹配到当前Route的时候被执行,返回的jsx对象或者组件会被渲染)
- Redirect是react-router-dom上的一个组件,作用是用来进行重定向的,有一个to属性就是要重定向到的路由path,to的值是一个对象,pathname属性表示重定向的path地址,其他属性会被打成一个location对象传给重定向后的路由组件的props
- 如果需要用户登录后还跳转回当前页面呢?
- 上面render函数的props路由对象中有我们当前的路由地址,我们可以通过props.match.url获取到,然后在我们重定向到登录页的时候将我们获取到的地址传过去,然后在用户登录成功后在通过编程式导航切回来:this.props.history.push(this.props.location.from) 当然我们也可以用受保护组件来实现其他功能
自定义菜单样式
我们写vue的时候知道在vue中当导航被激活的时候可以添加router-link-action类样式来当做激活样式,那么在react-router中呢? 还是使用组件包装来实现 自定义MenuLink组件
import React, { Component } from 'react'
import { Route, Link } from 'react-router-dom'
export default ({ to, label }) => {
return <Route path={to} children={(props) => {
return <li className={props.match ? 'active' : ''}>
<Link to={to}>{label}</Link>
</li>
}
}></Route>
}
-
MenuLink组件返回一个Route组件,在Route组件中有一个children属性,属性值依旧是一个方法,方法的参数props也是当前路由信息对象,我们在其中判断当前路由是否被激活,怎么判断?
-
如果路由被激活则当前路由对象中的match属性是一个对象,如果没有被激活这match属性是null,我们就通过这个来判断,如果激活了就为其添加active类名,没激活就不添加,active类名就是我们定义的选中时样式
-
children 和 render的区别: 虽然值都是一个函数,返回的都是一个jsx对象或者组件 render在页面的url与当前Route匹配时被调用,将返回jsx对象或者组件渲染 children则是不管页面你的url和当前Route是否匹配都会被调用,返回的jsx对象或者组件会被渲染
-
其实套路都是一样的,就是使用我们的组件将Route包裹起来,在我们的组价中做逻辑判断然后选择性的返回一个Route组件出来
antd(Ant Design )按需引入以及使用
antd按需引入
-
create-react-app搭建的项目中按需引入antd以及配置Less
-
使用creat-react-app搭建的项目中的webpack文件是隐藏起来的 暴露wenpack文件的指令是yarn eject. 在使用这个指令之前要先推送一次git文件才行,或者删除git文件
-
运行之后会询问是否暴露,输入y即可。
-
此时在项目目录下会多出一个config文件夹。
-
按需引入antd:
-
安装babel-plugin-import npm i babel-plugin-import -sava
-
在根目录下的package.json下的bable中添加相应代码即可 "babel": { "presets": [ "react-app" ], "plugins": [ [ "import", { "libraryName": "antd", "style": "css" // 引入样式为 css // style为true 则默认引入less } ] ] }
-
然后就可以直接使用import { Button } from 'antd'来按需引入的,不需要先引入全局的import 'antd/dist/antd.css'再引入import Button from 'antd/es/button';
-
配置less creat-react-app搭建的项目中默认没有为我们配置less,如果想用less需要自己配置,也要先使用npm run eject暴露出配置文件来 安装less: npm i less less-loader -save
-
在暴露出来的webpack中找到webpack.config.js文件,需要首先在上面的一大堆cosnt常量定义中加入 const lessRegex = /.less
/; 这是用来识别less的
然后在其module的rules中添加如下代码: { test: lessRegex, exclude: lessModuleRegex, use: getStyleLoaders( { importLoaders: 2, sourceMap: isEnvProduction && shouldUseSourceMap, }, 'less-loader' ), // Don't consider CSS imports dead code even if the // containing package claims to have no side effects. // Remove this when webpack adds a warning or an error for this. // See github.com/webpack/web… sideEffects: true, }, { test: lessModuleRegex, use: getStyleLoaders( { importLoaders: 2, sourceMap: isEnvProduction && shouldUseSourceMap, modules: true, getLocalIdent: getCSSModuleLocalIdent, }, 'less-loader' ), },