react-router路由

·  阅读 4408

安装

npm i react-router-dom --save
复制代码

容器组件

  • BrowserRouter 浏览器自带的H5 API, restful 风格,需要配合后台;
  • HashRouter 使用 hash 方式进行路由,路径后均有#
  • MemoryRouter 在内存中管理 history ,地址栏不会变化。在 reactNative 中使用。

路由的使用

  1. 跑通路由
//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 )按需引入以及使用

中文文档:ant.design/docs/react/…

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/;
const lessModuleRegex = /\.module\.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' ), },

分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改