React - router的使用 && 结合react-red

2020-08-07  本文已影响0人  闪电西兰花
"react-router-dom": "^5.2.0"
// src/components/RouteSample.js

import React from 'react';
// 引入路由需要的基础模块
import {BrowserRouter, Link, Route} from 'react-router-dom'

export default function RouteSample () {
  return (
    <div>
      <BrowserRouter>
        <div>

          {/* 导航链接 */}
          <div><Link to="/">首页</Link></div>
          <div><Link to="/about">关于</Link></div>

          {/* 路由配置:路由就是组件 */}
          <Route path="/" component={Home}></Route>
          <Route path="/about" component={About}></Route>

        </div>
      </BrowserRouter>
    </div>
  )
}
// src/components/RouteSample.js

function Home() {
  return <div>
    <h5>Home</h5>
  </div>
}

function About () {
  return (
    <div>
      <h5>About</h5>
    </div>
  )
}
{/* 路由配置:路由就是组件 */}
<Route exact path="/" component={Home}></Route>
<Route path="/about" component={About}></Route>
// src/components/RouteSample.js

function Home() {
  return <div>
    <h5>Home</h5>
    <ul>
      <li><Link to="/detail/web">web</Link></li>
      <li><Link to="/detail/ios">ios</Link></li>
    </ul>
  </div>
}
// src/components/RouteSample.js

{/* 新增详情页路由 lesson就是动态传参的部分*/}
<Route path="/detail/:lesson" component={Detail}></Route>
// src/components/RouteSample.js

// 新增详情页组件

// 传递进来的是路由器对象
// 路由器对象主要包含以下3部分,可以结合下面的具体截图理解
// 1. history  导航指令  history.goBack
// 2. match 获取参数信息
// 3. location 当前url信息
function Detail (routeParams) {
  console.log('routeParams',routeParams)
  return (
    <div>
      当前课程:{routeParams.match.params.lesson}
      <button onClick={routeParams.history.goBack}>后退</button>
    </div>
  )
}
路由器参数.jpg
// src/components/RouteSample.js

// 新增404页面组件 展示访问的具体路径不存在
function NoMatch ({location}) {
  return (
    <div>404, {location.pathname}不存在</div>
  )
}

// 新增404路由
{/* 404页面没有path 当有path的路由都不匹配时那必然匹配404*/}
<Route component={NoMatch}></Route>
首页展示404.jpg
ios详情页显示404.jpg
// src/components/RouteSample.js

import React from 'react';
// 引入Switch
import {BrowserRouter, Link, Route, Switch} from 'react-router-dom'

{/* 路由配置:路由就是组件 */}
{/* 用Switch包裹路由配置,避免展示包容式路由 */}
<Switch>
  <Route exact path="/" component={Home}></Route>
  <Route path="/about" component={About}></Route>
  <Route path="/detail/:lesson" component={Detail}></Route>
  {/* 404页面没有path 当有path的路由都不匹配时那必然匹配404*/}
  <Route component={NoMatch}></Route>
 </Switch>
路由不存在显示404.jpg
// src/components/RouteSample.js

// 当前用户信息
function About () {
  return (
    <div>
      <h5>About</h5>
      <div>
        <Link to="/about/me">个人信息</Link>
        <Link to="/about/order">订单信息</Link>
      </div>
      <Switch>
        <Route path="/about/me" component={() => (<div>me</div>)}></Route>
        <Route path="/about/order" component={() => (<div>order</div>)}></Route>
      </Switch>
    </div>
  )
}
about默认不展示嵌套路由内容.jpg
// src/components/RouteSample.js

import {BrowserRouter, Link, Route, Switch, Redirect} from 'react-router-dom'

<Switch>
  <Route path="/about/me" component={() => (<div>me</div>)}></Route>
  <Route path="/about/order" component={() => (<div>order</div>)}></Route>
  {/* 路由默认项 */}
  <Redirect to="/about/me"></Redirect>
</Switch>
// src/components/RouteSample.js

// 保留路由组件所需的参数component、以及其他参数例如pth等,同时传一个登录状态isLogin
function PrivateRoute ({component: Comp, isLogin, ...rest}) {
  return (
    // render函数 根据条件动态渲染组件
    // 未登录则重定向至登录页
    // 登录路由也配置了一个redirect,这样在设计登录组件的时候当登录成功即重定向跳转至登录前访问的页面
    <Route
      {...rest}
      render = {
        props => isLogin ? (<Comp></Comp>) : (<Redirect
          to={{pathname: "/login", state: {redirect: props.location.pathname}}}
        ></Redirect>)
      }
    ></Route>
  )
}
// src/components/RouteSample.js

// 从路由参数拿到重定向地址,从redux获取登录状态和登录方法
function Login ({location, isLogin, login}) {
  const redirect = location.state.redirect || '/'
  if(isLogin) {
    return <Redirect to={redirect}></Redirect>
  }
  return (
    <div>
      <p>用户登录</p>
      <hr/>
      <button onClick={login}>login</button>
    </div>
  )
}


{/* 路由配置:路由就是组件 */}
<Switch>
  <Route exact path="/" component={Home}></Route>
  {/* 使用路由守卫 */}
  <PrivateRoute path="/about" component={About}></PrivateRoute>
  <Route path="/detail/:lesson" component={Detail}></Route>
  <Route path="/login" component={Login}></Route>
   {/* 404页面没有path 当有path的路由都不匹配时那必然匹配404*/}
  <Route component={NoMatch}></Route>
</Switch>
// src/store/user.redux.js

// 初始化状态,没在登录中 并且 未登录
const initial = {
  isLogin: false,
  loading: false
}

export const user = (state = initial, action) => {
  switch(action.type) {
    // 登录中
    case "requestLogin":
      return {
        isLogin: false,
        loading: true
      };
    // 已登录 
    case "login":
      return {
        isLogin: true,
        loading: false
      };
    default:
      return state;
  }
}

// 请求登录异步调用时,先修改状态为登录中
export const login = () => dispatch => {
  dispatch({type: 'requestLogin'});
  setTimeout(() => {
    dispatch({type: 'login'})
  }, 1500);
}
// src/store/index.js

// applyMiddleware 应用中间件方法
import {createStore, applyMiddleware, combineReducers} from 'redux';
import logger from 'redux-logger'
import thunk from 'redux-thunk'
import {user} from './user.redux'

const store = createStore(
  combineReducers({user}),
  applyMiddleware(logger, thunk)
);

export default store;
// src/components/RouteSample.js

// 添加引用
import {connect} from 'react-redux';
import {login} from '../store/user.redux'

// 路由守卫
const PrivateRoute = connect(
  state => ({isLogin: state.user.isLogin})
)(
  ({component: Comp, isLogin, ...rest}) => {
    return (
      // render 根据条件动态渲染组件
      <Route
        {...rest}
        render={
          props => isLogin ? 
          (<Comp></Comp>) : 
          (<Redirect
            to={{pathname: "/login", state: {redirect: props.location.pathname}}}
          ></Redirect>)
        }
      >
      </Route>
    )
  }
)

// 登录组件
const Login = connect(
  // 映射状态与dispatch方法
  state => ({
    isLogin: state.user.isLogin,
    loading: state.user.loading
  }),
  {login}
)(
  ({location, isLogin, login, loading}) => {
    const redirect = location.state.redirect || '/'
    if(isLogin) {
      return <Redirect to={redirect}></Redirect>
    }
    return (
      <div>
        <p>用户登录</p>
        <hr/>
        {/* loading优化 */}
        <button onClick={login} disabled={loading}>
          {loading ? 'login...' : 'login'}
        </button>
      </div>
    )
  }
)
// App.js

import store from './store/index'
import {Provider} from 'react-redux'

import RouteSample from './components/RouteSample'

{/* router */}
<Provider store={store}>
  <RouteSample></RouteSample>
</Provider>
上一篇 下一篇

猜你喜欢

热点阅读