AcWing
  • 首页
  • 活动
  • 题库
  • 竞赛
  • 应用
  • 更多
    • 题解
    • 分享
    • 商店
    • 问答
    • 吐槽
  • App
  • 登录/注册

Web应用课——5.3 React——路由(route-app)

作者: 作者的头像   ._675 ,  2023-05-25 23:18:24 ,  所有人可见 ,  阅读 46


0


屏幕截图 2023-05-25 231103.png
屏幕截图 2023-05-25 184754.png

目录结构:

屏幕截图 2023-05-25 231300.png

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './components/app';
import { BrowserRouter } from 'react-router-dom';
import 'bootstrap/dist/css/bootstrap.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  //如果要给前端页面加路由的话,一定要把组件包含在BrowserRouter里面
  <BrowserRouter>
    <App />
  </BrowserRouter>

);

app.jsx

import React, { Component } from 'react';
import NavBar from './navbar';
import Home from './home';
import Linux from './linux';
import Django from './django'
import Web from './web';
import WebContent from './webContent';
import NotFound from './notFound';
import {Routes,Route} from 'react-router-dom';
import { Navigate } from 'react-router-dom';

//写路由:根据当前的url去选择我们在下面显示哪一个组件

class App extends Component {
    state = {  } 
    render() { 
        return (
            <React.Fragment>
                <NavBar />
                {/* 如果想写多个路由的话,一定要将所有路由包含在routes里面 */}
                {/* container也是bootstrap里的一个类,他可以动态的调整填充区域的内容,响应式的调整填充区域的内容 */}
                <div className='container'>
                    <Routes>
                        <Route path='/' element={<Home />}/>

                        {/* 嵌套路由 */}
                        <Route path='/linux' element={(<Linux />
                            // <div>
                            //     hhh
                            //     <a href="/">返回首页</a>
                            // </div>
                        )}>
                            <Route path='homework' element={<h4>homework的内容</h4>}></Route>
                            <Route path='terminal' element={<h4>terminal的内容</h4>}></Route>
                            <Route path='*' element={<h4>其他</h4>}></Route>
                        </Route>

                        {/* 给组件Django传一个参数,直接在组件里写就可以了 */}
                        <Route path='/django' element={<Django id='hhh' />}/>
                        <Route path='/web' element={<Web />}/>
                        {/* 将/web/conntent/1中1变成一个变量可以写成:chapter,这样1这个位置的内容就会被保存到名字是chapter这个变量里面 */}
                        {/* 如果有多个参数每一个参数用一个冒号 */}
                        {/* <Route path='web/content/:chapter/:section' element={<WebContent />}/> */}

                        {/* 用第二种方式来获取参数,路由匹配的时候,他只匹配到问号前面的部分,问号后面的部分它是不匹配的 */}
                        <Route path='/web/content' element={<WebContent />}/>
                        <Route path='/404' element={<NotFound />} />

                        {/* 重定向
                        如果打开一个新的页面之后,如果这个页面不存在的话,就把他重定向到404 
                        通配符* path="*"表示它可以匹配所有的路径
                        Navigate的属性to表示我们需要跳到哪一个链接里面*/}
                        <Route path='*' element={<Navigate replace to="/404" />}/>
                    </Routes>
                </div>

            </React.Fragment>

        );
    }
}

export default App;

navbar,js

import React, { Component } from 'react';
import { Link } from 'react-router-dom';

class NavBar extends Component {
    state = {  } 
    render() { 
        return (
            <nav className="navbar navbar-expand-lg bg-body-tertiary">
                <div className="container-fluid">
                    {/* 实现每次不重复加载页面,Link组件可以直接让当前页面假装跳到另外一个页面,但其实并没有向后端发请求
                    将所有的a标签都变成Link,
                    <a className="navbar-brand" href="/">讲义</a> */}
                    <Link className='navbar-brand' to='/'>讲义</Link>
                    <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
                    <span className="navbar-toggler-icon"></span>
                    </button>
                    <div className="collapse navbar-collapse" id="navbarNavAltMarkup">
                        <div className="navbar-nav">
                            {/* <a className="nav-link active" aria-current="page" href="/">Home</a>
                            <a className="nav-link" href="/linux">Linux</a>
                            <a className="nav-link" href="/django">Django</a>
                            <a className="nav-link" href="/web">Web</a> */}
                            {/* 前端渲染,每次点完一个按钮之后,他并没有真的打开这个链接 */}
                            {/* 如果想给后端发请求返回整个页面的话就用一般的Link(a标签),如果不想给后端发请求,只想假装改变页面的话就用link(Link标签) */}
                            <Link className="nav-link" aria-current="page" to="/">Home</Link>
                            <Link className="nav-link" to="/linux">Linux</Link>
                            <Link className="nav-link" to="/django">Django</Link>
                            <Link className="nav-link" to="/web">Web</Link>
                        </div>
                    </div>
                </div>
            </nav>
        );
    }
}

export default NavBar;

home.jsx

import React, { Component } from 'react';

class Home extends Component {
    state = {  } 
    render() { 
        return (
            <h1>Home</h1>
        );
    }
}

export default Home;

linux.js

import React, { Component } from 'react';
import { Outlet } from 'react-router-dom';
// Outlet可以用来填充我们linux子组件里的路由的内容

class Linux extends Component {
    state = {  } 
    render() { 
        return (
            <React.Fragment>
                <h1>Linux</h1>
                <hr />

                {/* 在地址栏输入http://localhost:3000/linux/homework可以渲染出来Linux子组件homework的内容
                在地址栏输入http://localhost:3000/linux/terminal可以渲染出来Linux子组件terminal的内容 */}
                <Outlet />
            </React.Fragment>


        );
    }
}

export default Linux;

django.jsx

import React, { Component } from 'react';

class Django extends Component {
    state = {  } 
    render() { 
        console.log(this.props.id);
        return (
            <h1>Django</h1>
        );
    }
}

export default Django;

web.jsx

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
class Web extends Component {
    state = { 
        webs:[
            {id:1,title:"HTML"},
            {id:2,title:"CSS"},
            {id:3,title:"JavaScript"},
            {id:4,title:"拳皇"},
            {id:5,title:"React"},
        ]
     } 
    render() { 
        //要渲染一个标题和一个内容所以要渲染两个东西,两个东西就需要先将他用React.Framement先括起来
        return (
            <React.Fragment>
                <h1>Web</h1>
                <hr />
                <div>
                    {this.state.webs.map(web=>(
                        //循环里面每一个组件都有一个唯一的key,唯一的key可以搞成id
                        //给每一个元素加上一个链接,前端渲染加链接要放到Link里面
                        <div key={web.id}>
                            {/* <Link to={`/web/content/${web.id}`}>{web.id+"."+web.title}</Link> */}
                            {/* 2 */}
                            <Link to={`/web/content?chapter=${web.id}`}>{web.id+"."+web.title}</Link>
                        </div>
                    ))}
                </div>

            </React.Fragment>

        );
    }
}

export default Web;

webContent.jsx

import React, { Component } from 'react';
// 1
import { useParams } from 'react-router-dom';
// 2
import { useSearchParams } from 'react-router-dom';
import { Link } from 'react-router-dom';

//传参数的方式
// 1.直接在url里面写
// http://localhost:3000/web/content/1/3
// 2.通过url里面传参数的话,可以在问好后面写,变量名等于什么值
// http://localhost:3000/web/content?chapter=1&section=3


//如果是类组件的话,不能直接在类组件中访问useParams
//有两种修改方式,1.直接将类组件变成函数组件 
//2.虽然在类里不能用但在调用这个类之前可以用,即在类外面用
class WebContent extends Component {
    state = { 
        // useSearchParams是一个数组有两个值,第一个值是获取参数,第二个值是设置参数
        //这个两个都是函数
        searchParams:this.props.params[0],//获取某一个参数
        setSearchParams:this.props.params[1],//将我们链接里面的参数设置成什么然后重新渲染当前页面
     };
    render() { 
        // 1
        // console.log(this.props.params);
        // 2
        // console.log(this.state.searchParams.get('section'));
        return (
            <React.Fragment>
                {/* 把那个数字取出来 */}
                <h1>Web - {this.state.searchParams.get('chapter')}</h1>
                <div>内容</div>
                <hr />
                <Link to='/web'>返回</Link>
            </React.Fragment>

        );
    }
}

// export default WebContent;

//返回一个匿名函数,这个匿名函数会返回一个组件,这个匿名函数就是一个匿名组件,其实就是一个函数组件,外面本质上还是在函数组件里用的,但是外面相当于是在类组件外面套了一层函数组件
export default (props)=>(
    <WebContent 
        {...props}//把函数组件里的属性展开
        params={useSearchParams()}//再将它的值作为一个属性传进去就可以了
    />
);

//sfc函数组件 
// const WebContent = () => {
//     console.log(useParams());
//     return (

//         <h1>Web - 1</h1>
//     );
// }

// export default WebContent;

notFound.jsx

//当找不到页面的时候返回404页面
import React, { Component } from 'react';

class NotFound extends Component {
    state = {  } 
    render() { 
        return (
            <h1>NotFound</h1>
        );
    }
}

export default NotFound;

0 评论

你确定删除吗?

© 2018-2023 AcWing 版权所有  |  京ICP备17053197号-1
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息