React全家桶之react-router-domV6基础教程

单页面应用程序

  • SPA: Single Page Application 单页面应用程序,整个应用只有一个页面(index.html)
  • MPA: Multiple Page Application 多页面应用程序,整个应用中有很多页面(*.html)

SPA优势

  1. 更快的页面加载速度: 在SPA中,大部分资源(HTML、CSS、Scripts)仅在网站加载时请求一次。之后的页面更新通过Ajax请求获取必要的数据,仅替换页面的部分内容而不是加载整个新页面。这减少了页面加载时间,提供了更快的用户体验。
  2. 更流畅的用户体验: SPA可以实现无刷新切换页面,这意味着应用可以像桌面应用那样流畅。用户不需要等待页面重新加载,从而提高了交互性和用户满意度。
  3. 前后端分离: SPA允许开发者在前端和后端之间建立清晰的界限。后端专注于API开发,而前端则处理用户界面和用户体验,这种模式便于团队协作和应用维护。
  4. 更好的移动端适应性: 由于SPA在设计时就考虑到了动态内容更新,因此它们通常可以更容易地适应不同的屏幕尺寸和设备。这对于创建响应式设计和跨平台应用尤其有利。
  5. 简化的调试过程: 使用如Chrome的开发者工具,SPA的调试过程可以更加直接和高效。开发者可以轻松查看网络操作、调查页面元素和数据绑定。
  6. 减少服务器负载: SPA在用户与应用交互过程中减少了对服务器的请求。由于大部分页面逻辑都在客户端完成,因此可以减轻服务器负载。

SPA缺点

不利于SEO优化(搜索引擎优化)

  • 搜索引擎爬虫只会进行HTML页面的文本内容,不会执行JS代码

如何解决这个问题?
使用SSR(服务端渲染)来解决SEO问题,直接给浏览器渲染一个纯HTML的内容,或者使用页面静态化。

React路由介绍

使用单个页面管理更多的页面,进行开发SPA应用

  • 前端路由的功能:让用户从一个页面导航到另外一个页面
  • 页面路由是一套映射规则,在React中,是URL路径和组件的对应关系
  • 使用React路由简单来说就是:配置路径和组件

手动实现单页面应用程序

1.创建三个字组件分别是My.js Friend.js Home.js,然后调用componentDidMount这个钩子函数,在改变锚节点的时候获取到相应的链接,在渲染的时候用JSP进行判断即可,详细请看下面代码(React18写法):

import React, { Component } from 'react';
import { createRoot } from 'react-dom/client'; // Import createRoot
import Home from "./pages/Home";
import Friend from "./pages/Friend";
import My from "./pages/My";

class Index extends Component {
    state = {
        currentHash: ''
    };

    componentDidMount() {
        window.addEventListener('hashchange', () => {
            this.setState({
                currentHash: window.location.hash.slice(1)
            });
        });
    }

    render() {
        const { currentHash } = this.state;
        return (
            <div>
                <h1>组件</h1>
                <ul>
                    <li><a href="#/home">home</a></li>
                    <li><a href="#/my">my music</a></li>
                    <li><a href="#/friend">my Friend</a></li>
                </ul>
                {currentHash === '/home' ? <Home /> : null}
                {currentHash === '/my' ? <My /> : null}
                {currentHash === '/friend' ? <Friend /> : null}
            </div>
        );
    }
}

// Use createRoot to render the application
const container = document.getElementById('root');
const root = createRoot(container); // Create a root.
root.render(<Index />); // Initial render

React-router-dom

React-router-dom目前有两个版本一个版本是v6版本一个是V5版本二者存在语法上的差异,我的这个版本是以V6版本为例

安装

install add react-router-dom

导入核心组件

import {HashRouter, Route, Link} from 'react-router-dom'

在Index页面中如何导入三个组件

import React, { Component } from 'react';
import { createRoot } from 'react-dom/client';
import { HashRouter, Routes, Route, Link } from 'react-router-dom';
import Home from './pages/Home';
import Friend from './pages/Friend';
import My from './pages/My';

class Index extends Component {
    state = {
        currentHash: window.location.hash.slice(1)
    };

    componentDidMount() {
        window.addEventListener('hashchange', this.handleHashChange);
    }

    componentWillUnmount() {
        window.removeEventListener('hashchange', this.handleHashChange);
    }

    handleHashChange = () => {
        this.setState({
            currentHash: window.location.hash.slice(1)
        });
    };

    render() {
        return (
            <HashRouter>
                <div>
                    <h1>组件</h1>
                    <ul>
                        <li>
                            <Link to="/home">首页</Link>
                        </li>
                        <li>
                            <Link to="/my">我的音乐</Link>
                        </li>
                        <li>
                            <Link to="/friend">我的盆友</Link>
                        </li>
                    </ul>
                    <Routes>
                        <Route path="/home" element={<Home />} />
                        <Route path="/my" element={<My />} />
                        <Route path="/friend" element={<Friend />} />
                    </Routes>
                </div>
            </HashRouter>
        );
    }
}

const container = document.getElementById('root');
const root = createRoot(container);
root.render(<Index />);

使用HashRouter进行包裹,并且使用Routes进行点击路由显示具体组件的内容包裹,替换原本的判断路由使用Route,里面传递两个属性,Path具体的路由路径,element渲染节点组件
注意:一个项目中只有一个HashRouter

Router详细说明

在React中Router有两种形式

  1. HashRouter:使用URL哈希实现,监听hashchange事件来进行实现(http://localhost/3000/#/page)
  2. BrowerRouter:使用h5的哈希API实现,监听popstart事件进行实现(http://localhost/3000/page)
<Route path="/" element={<Home />}></Route>
<Route path="/my" element={<My />} />

注意:这时候路由会匹配到“/”只要有出现“/”开头路由都会进行匹配

精确匹配

<Route exact path="/" element={<Home />}></Route>
exact属性可以进行路由的精确匹配,必须符合path要求否则不显示组件

Routes组件

处理,当遇到没有发现路由匹配的地址时,出现404组件,可以进行自定义404页面

<Routes>
                        <Route path="/home" element={<Home />} />
                        <Route path="/my" element={<My />} />
                        <Route path="/friend" element={<Friend />} />
                        <Route path="*" element={<Page404 />} />
                    </Routes>

路由执行的过程

1.点击Link组件,修改了浏览器地址栏中的url
2.React路由间听到地址栏url的变化
3.React路由内部便利所有的Route组件,使用路由规则(path)与 pathname(hash)进行匹配
4.当路由规则(path)能够匹配地址栏中的pathname(hash)时,就该展示Route组件的内容

嵌套路由

我想在my中渲染两个路由,一个是我的主页,一个是我的音乐

import React, { Component } from 'react';
import { createRoot } from 'react-dom/client';
import { HashRouter, Routes, Route, Link } from 'react-router-dom';
import Home from './pages/Home';
import Friend from './pages/Friend';
import My from './pages/My';  // Assuming My is correctly imported
import Page404 from './pages/Page404';
import Music from './pages/music';  // Correct if file is named 'music.js'
import Myself from './pages/Myself';

class Index extends Component {
    render() {
        return (
            <HashRouter>
                <div>
                    <h1>组件</h1>
                    <ul>
                        <li>
                            <Link to="/home">首页</Link>
                        </li>
                        <li>
                            <Link to="/my">我的音乐</Link>
                        </li>
                        <li>
                            <Link to="/friend">我的盆友</Link>
                        </li>
                    </ul>
                    <Routes>
                        <Route path="/home" element={<Home />} />
                        <Route path="/my" element={<My />}>
                            <Route path="mymusic" element={<Music />} />
                            <Route path="meself" element={<Myself />} />
                        </Route>
                        <Route path="/friend" element={<Friend />} />
                        <Route path="*" element={<Page404 />} />
                    </Routes>
                </div>
            </HashRouter>
        );
    }
}

const container = document.getElementById('root');
const root = createRoot(container);
root.render(<Index />);

主函数中使用Route进行缩进

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

class My extends Component {
    render() {
        return (
            <div>
                我是My组件
                <ul>
                    <li>
                        <Link to="/my/mymusic">我的音乐</Link>
                    </li>
                    <li>
                        <Link to="/my/meself">我的主页</Link>
                    </li>
                </ul>
                <Outlet/>
            </div>
        );
    }
}

export default My;

my组件中使用Link进行引导组件,并且在to属性中必须携带父组件地址,使用Outlet进行组件进行遍历

Navigate重定向

import React, { Component } from 'react';
import { createRoot } from 'react-dom/client';
import { HashRouter, Routes, Route, Link,Navigate} from 'react-router-dom';
import Home from './pages/Home';
import Friend from './pages/Friend';
import My from './pages/My';  // Assuming My is correctly imported
import Page404 from './pages/Page404';
import Music from './pages/music';  // Correct if file is named 'music.js'
import Myself from './pages/Myself';
class Index extends Component {
    render() {
        return (
            <HashRouter>
                <div>
                    <h1>组件</h1>
                    <ul>
                        <li>
                            <Link to="/home">首页</Link>
                        </li>
                        <li>
                            <Link to="/my">我的音乐</Link>
                        </li>
                        <li>
                            <Link to="/friend">我的盆友</Link>
                        </li>
                    </ul>
                    <Routes>
                        <Route path="/" element={<Navigate to="/home" />} />
                        <Route path="/home" element={<Home />} />
                        <Route path="/my" element={<My />}>
                            <Route path="mymusic" element={<Music />} />
                            <Route path="meself" element={<Myself />} />
                        </Route>
                        <Route path="/friend" element={<Friend />} />
                        <Route path="*" element={<Page404 />} />
                    </Routes>
                </div>
            </HashRouter>
        );
    }
}

const container = document.getElementById('root');
const root = createRoot(container);
root.render(<Index />);

在代码28行可以看到我的给首页设置了个重定向,到home,使用组件Navigate

编程式导航

通过编程的方法进行导航,例如点击按钮登陆,登陆后跳转到后台首页

import React from 'react';
import { useNavigate } from 'react-router-dom';

function Friend() {
    const navigate = useNavigate();

    const handleClick = () => {
        console.log('登陆成功');
        navigate('/home'); // Navigate to the homepage
    };

    return (
        <div>
            我是Friend组件
            <button onClick={handleClick}>登陆</button>
        </div>
    );
}

export default Friend;

使用useNavigate进行路由跳转,useNavigate 是 React Router v6 中提供的一个 hook,它用于在函数组件中进行编程式导航,即在不通过 组件或 history 对象的情况下,在代码中手动执行导航操作。

动态路由和动态路由参数的获取

import React, { Component } from 'react';
import { createRoot } from 'react-dom/client';
import { Routes, BrowserRouter, Route, Link } from "react-router-dom";
import Detailed from "./pages/detailed";

class Index extends Component {
    render() {
        return (
            <BrowserRouter>
                <div>
                    详情页
                    <ul>
                        <li><Link to="/detailed/1">商品1</Link></li>
                        <li><Link to="/detailed/2">商品2</Link></li>
                        <li><Link to="/detailed/3">商品3</Link></li>
                    </ul>
                    <Routes>
                        <Route path="/detailed/:id" element={<Detailed />} />
                    </Routes>
                </div>
            </BrowserRouter>
        );
    }
}

const container = document.getElementById('root');
const root = createRoot(container);
root.render(<Index />);

在原来的路由匹配把第二个参数改为“:id”的形式进行参数传递

import React from 'react';
import { useParams } from 'react-router-dom';

const DetailComponent = () => {
    const { id } = useParams();

    return (
        <div>
            <h2>Detail Component</h2>
            <p>ID: {id}</p>
        </div>
    );
}

export default DetailComponent;

useParams 返回一个对象,其中包含了所有与当前路由匹配的参数。在这个例子里,这个对象将有一个名为 Id 的属性,其值为当前URL中对应位置的实际字符串。

原文链接:https://juejin.cn/post/7343206380696387610 作者:半世浮生

(0)
上一篇 2024年3月7日 下午4:52
下一篇 2024年3月7日 下午5:02

相关推荐

发表回复

登录后才能评论