React第四篇 路由&Hooks

5,298 阅读4分钟

React 学习笔记

完整代码戳git

第一部分,腾讯课堂react入门课程
课程地址
React第一篇 npm、yarn介绍
React第二篇 React语法
React第三篇 单页应用开发
React第四篇 路由&Hooks
React第五篇 综合应用(登录+列表)

第二部分,Redux课程
课程地址
React第六篇 Redux
React第七篇 React Redux


1.React-Router

1.1 路由基本配置

  • BrowserRouter/HashRouter
    • BrowserRouter /xx 方式访问
    • HashRouter #/xxx 方式访问
  • Switch:react 4.0 新增特性,目前已更新到5.0+版本
    • 匹配
  • Route-exect/path/component
    • 根据地址精确匹配
  • Link/NavLink
    • 路由封装

安装

  • yarn add react-router-dom

完整代码

  • src下新建pages包演示多页面路由功能
  • 在pages下新建simplerouter包编写代码 ①首先在src下新建router.js
// import {BrowserRouter as Router,Route,Switch} from "react-router-dom";
import {HashRouter as Router,Route,Switch} from "react-router-dom";
import React from 'react'
import App from "./pages/simplerouter/app";
import Login from "./pages/simplerouter/login";
import Home from "./pages/simplerouter/home";

/**
 * @Description: 路由
 * @author dongshuhuan
 * @date 2020-05-16
 */
export default function IRouter(){
    return  <Router>
            {/*普通方式,根据path匹配,但是App的内容会出现在Login上方 ->图1所示*/}
            {/*<Route path = "/" component={App}></Route>*/}
            {/*<Route path = "/login" component={Login}></Route>*/}
            {/*<Route path = "/home" component={Home}></Route>*/}

        {/*如果用swithc,浏览器输入/home也只会加载App页,因为/home先匹配了/*/}
        {/*加上 exact 可以精准匹配 ->图2所示*/}
        {/*如果导入的是HashRouter,会自动加上# 如 http://localhost:3000/login#/ ->图3所示*/}
        <Switch>
            <Route exact path = "/" component={App}></Route>
            <Route path = "/login" component={Login}></Route>
            <Route path = "/home" component={Home}></Route>
        </Switch>

    </Router>
}

图1

图2

图3

②src下修改index.js

import React from 'react';
import ReactDOM from 'react-dom';
import * as serviceWorker from './serviceWorker';
import Router from "./router";

ReactDOM.render(
  <React.StrictMode>
    <Router/>
  </React.StrictMode>,
  document.getElementById('root')
);

serviceWorker.unregister();

③pages/simplerouter/app.js

import React from 'react'
import {Link} from "react-router-dom";
import './app.scss'
import {Button} from 'antd'
import 'antd/dist/antd.css'

/**
 * @Description:
 * @author dongshuhuan
 * @date 2020-05-16
 */

// export default function App() {
//     return <div  class="container">
//         <h1>欢迎来到React的世界</h1>
//         {/*Link的使用*/}
//         {/*如果是HashRouter  浏览器地址栏输入http://localhost:3000/#/login#/即可跳转到登录页 */}
//         <Link to="/login">点击跳转到登录页</Link>
//         <br/>
//         <Link to="/home">点击跳转到主页面</Link>
//         <br/>
//     </div>
// }


//有状态组件
export default class App extends React.Component{

    handleJump=()=>{
        this.props.history.push("/login");
    }

    render() {
        return <div className="container">
            <h1>欢迎来到React的世界</h1>
            {/*Link的使用*/}
            {/*如果是HashRouter  浏览器地址栏输入http://localhost:3000/#/login#/即可跳转到登录页 */}
            <Link to="/login">点击跳转到登录页</Link>
            <br/>
            <Link to="/home">点击跳转到主页面</Link>
            <br/>
            <Button onClick={this.handleJump}>登录跳转登录</Button>
        </div>
    }
}

④pages/simplerouter/home.js

import React from 'react'

export default function Home() {
    return <div>This is Home</div>
}

⑤pages/simplerouter/login.js

import React from 'react'

export default function Login() {
    return <div>This is Login</div>
}

1.2 路由动态配置

  • detail/2020
  • Redirect/404
  • JS中路由跳转 router.js中新增以下代码
 {/*动态路由 浏览器输入http://localhost:3000/#/detail/123 即可看到效果*/}
    <Route path = "/detail/:goodsId" component={Detail}/>
    {/*重定向*/}
    <Route path = "/detail/:goodsId" component={Detail}>
        <Redirect to={'/login'}/>
    </Route>
    {/*404* 如果都没匹配到  输入http://localhost:3000/#/goods等不存在的路径即可看到效果 */}
    <Route path = "*" component={NoMatch}/>

detail.js & 404.js

export default class Detail extends React.Component{

    render() {
        return <div className="container">
            <h1>this is detail</h1>
        </div>
    }
}

export default function NoMacth() {
    return <div style={{color:'red'}}>404!!!</div>
}

1.3 React Hooks & 路由Hooks

React Hooks

用于解决函数式组件无状态问题

  • useState: 解决状态问题
  • useEffect:类似生命周期,didmount 和 didupdate中执行 修改app.js
export default function App() {
    //useState,效果与有状态组件state={}相同
    const [count,setCount] = useState(10);
    //useEffect 第二个参数传递空数组 log只会打印一次
    //可以在serCount修改初始值
    useEffect(()=>{
        console.log("执行了useEffect");
        setCount(100);
    },[])

    return <div  class="container">
        <h1>欢迎来到React的世界</h1>
        {/*Link的使用*/}
        {/*如果是HashRouter  浏览器地址栏输入http://localhost:3000/#/login#/即可跳转到登录页 */}
        <Link to="/login">点击跳转到登录页</Link>
        <br/>
        <Link to="/home">点击跳转到主页面</Link>
        <br/>
        {/*useState*/}
        <p>
            当前count次数:{count}
        </p>
        <Button onClick={()=>{setCount(count+1)}}>更新次数</Button>
    </div>
}

路由Hooks

  • useParams:获取参数(内部封装)
  • useHistory:通过js api操作路由跳转

useParams 如下图所示

图4

图5

useHistory 完整代码,修改detail.js

import {useParams,useHistory} from "react-router-dom";

export default function Detail() {
    //React Hooks
    // 1、useParams 使用 查看图5所示
    const params = useParams();
    //2、useHistory
    const history = useHistory();
    return <div  className="container">
        {/*useParams */}
        {/*<h1>this is detail</h1>*/}
        {/*<p>当前的参数json数据为:{JSON.stringify(params)}</p>*/}
        {/*<p>当前的参数值为:{params.goodsId}</p>*/}

        {/*useHistory*/}
        <h1>this is detail</h1>
        <p>当前的参数值为:{params.goodsId}</p>
        <Button onClick={()=>{
            history.push('/')
        }}>跳转</Button>
    </div>
}


//有状态组件
// export default class Detail extends React.Component{
//
//     jumpHome=()=>{
//         this.props.history.push('/')
//     }
//
//     render() {
//         return <div className="container">
//             <h1>this is detail</h1>
//             {/*根据地址获取参数 图4所示 */}
//             <p>当前的参数值为:{this.props.match.params.goodsId}</p>
//             <Button onClick={this.jumpHome}>跳转</Button>
//         </div>
//     }
// }