在使用create-react-app创建的React项目中进行页面导航(使用react-router-dom)

尝试使用 react-router-dom(v6.16.0) 来引入页面路由的 React 页面转换方法。
即使是 SPA,也有很多从页面中受益的地方,所以我想试一试。
当我在 package.json 中设置了 homepage 时,遇到了一点问题…
通过使用 process.env.PUBLIC_URL 来解决了这个问题,所以我在这里做了一些备忘。
我使用了基于 create-react-app 创建的项目作为基础,并删除了不需要的文件。
大致上的操作如下。

    • Reactプロジェクト作成 Win11

 

    • Reactプロジェクトから不要ファイル削除(./src直下削除)

 

    • Reactプロジェクトでページ遷移(react-router-dom v6.16.0使用)

react-router-dom インストール
ページのディレクトリ作成
ページ遷移の実装
ページ遷移の実装(コンポーネントにまとめる)
ページリンクのスタイル調整

最终成品可以在这里找到:
https://github.com/sueasen/my-app-react-router-dom

在 Windows 11 上创建 React 项目。

参考このページで、Node.jsのインストール方法を説明しています。

 

从React项目中删除不必要的文件(./src文件夹下的文件)

参考这个页面,我简单地把它分成了index.js和App.js做初始化。

 

在React项目中进行页面导航(使用react-router-dom v6.16.0)

安装 react-router-dom

只需要执行以下命令

npm i react-router-dom

创建页面目录

在src目录下创建一个名为pages的文件夹。

页面转换的实现

作为页面跳转的实际步骤,可以按照以下方式进行。

    • 遷移用ページのコンポーネント作成

BrowserRouter よりページ情報定義・表示
ページ遷移のリンク追加

创建迁移页面的组件

创建三个页面(主页、第一页、第二页),在每个页面的页面下方简单显示文字。
第二页设置为接收属性(参数)。

const Home = () => {
  return (
    <>
      <p>Home</p>
    </>
  );
};
export default Home;
const Page1 = () => {
  return (
    <>
      <p>Page1</p>
    </>
  );
};
export default Page1;
const Page2 = (props) => {
  return (
    <>
      <p>Page2 {props.text}</p>
    </>
  );
};
export default Page2;

通过BrowserRouter定义和显示页面信息

为了使用BrowserRouter在App.js中定义和显示页面信息,执行以下操作。

    • BrowserRouter, Routes, Route を react-router-dom からインポート

 

    • ページ用コンポーネントをインポート

 

    • BrowserRouter の basename に process.env.PUBLIC_URL を設定

process.env.PUBLIC_URL を設定すると homepage 設定した時などパスが狂わなくなる

Route に各々の path, element(コンポーネント) を設定

import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import Page1 from './pages/Page1';
import Page2 from './pages/Page2';

const App = () => {
  return (
    <>
      <h1>Hello World</h1>
      <p>App.jsx</p>
      {/* BrowserRouter, Routes, Route の定義、path に一致する element を表示 */}
      <BrowserRouter basename={process.env.PUBLIC_URL}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/page1" element={<Page1 />} />
          <Route path="/page2" element={<Page2 text="text sample" />} />
        </Routes>
      </BrowserRouter>
    </>
  );
};
export default App;
image.png

增加页面链接导航

如果添加了用于页面跳转的链接,就可以了。
在设置链接时,添加 process.env.PUBLIC_URL 到 basename 上,这样路径就不会错乱了。

import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import Page1 from './pages/Page1';
import Page2 from './pages/Page2';

const App = () => {
  return (
    <>
      <h1>Hello World</h1>
      <p>App.jsx</p>
      {/* 以下リンクを追加 */}
      <ul>
        <li>
          <a href={`${process.env.PUBLIC_URL}/`}>Home</a>
        </li>
        <li>
          <a href={`${process.env.PUBLIC_URL}/page1`}>Page1</a>
        </li>
        <li>
          <a href={`${process.env.PUBLIC_URL}/page2`}>Page2</a>
        </li>
      </ul>
      {/* BrowserRouter, Routes, Route を定義 */}
      <BrowserRouter basename={process.env.PUBLIC_URL}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/page1" element={<Page1 />} />
          <Route path="/page2" element={<Page2 text="text sample" />} />
        </Routes>
      </BrowserRouter>
    </>
  );
};

export default App;

image.png

将页面转换实现(整合到组件中)

将页面转换的实现汇总到组件中
通过定义并传递与页面转换相关的信息,创建一个返回页面转换链接的BrowserRouter组件
可能有更好的方法,但通过传递定义的信息,尝试将其转化为可行的形式

创建页面传输链接的组件

在pages文件夹下创建一个名为AppRouter.js的组件,该组件返回一个页面转移链接。

import { BrowserRouter, Routes, Route } from 'react-router-dom';

// pages は [{key:key1, path:path1, element:element1}, ...] を受け取る
export const appRouter = (pages) => {
  // BrowserRouter 返す処理
  const router = () => {
    return (
      <>
        <BrowserRouter basename={process.env.PUBLIC_URL}>
          <Routes>
            {pages.map((p) => (
              <Route key={p.key} path={p.path} element={p.element} />
            ))}
          </Routes>
        </BrowserRouter>
      </>
    );
  };
  // ページ遷移リンク 返す処理
  const links = () => (
    <ul>
      {pages.map((p) => (
        <li key={p.key}>
          <a href={`${process.env.PUBLIC_URL}${p.path}`}>{p.key}</a>
        </li>
      ))}
    </ul>
  );
  // BrowserRouter, ページ遷移リンク の定義を返す
  return {
    browserRouter: router(),
    navbarLink: links(),
  };
};

使用App.js中的AppRouer.js进行实现。

导入`pages`并将其定义为`AppRouer`的设置,然后使用`browserRouter`和`navbarLink`进行重写。

import { appRouter } from './pages/AppRouter';
import Home from './pages/Home';
import Page1 from './pages/Page1';
import Page2 from './pages/Page2';

// ページ情報を定義して appRouter に設定
const pages = [
  { key: 'Home', path: '/', element: <Home /> },
  { key: 'Page1', path: '/page1', element: <Page1 /> },
  { key: 'Page2', path: '/page2', element: <Page2 text="text sample" /> },
];
const router = appRouter(pages);

const App = () => {
  return (
    <>
      <h1>Hello World</h1>
      <p>App.jsx</p>
      {/* appRouter の navbarLink に書き換え*/}
      {router.navbarLink}
      {/* appRouter の browserRouter に書き換え*/}
      {router.browserRouter}
    </>
  );
};

export default App;

只要能执行并完成页面跳转就可以了!

页面链接样式调整

给菜单链接等应用样式

App.css : 新規作成、スタイルを定義

App.js : インポート追加 App.css

AppRouter.js : タグやクラス属性を追加

body {
    margin: 0;
    font-family: "Futura", Helvetica, sans-serif;
}

/* Navbar & Navmenu color */
:root {
    --background-navbar: rgba(55, 55, 55, 0.98);
    --height-navbar: 52px;
}

.header {
    background: var(--background-navbar);
    position: fixed;
    width: 100%;
    height: var(--height-navbar);
}

/* Nav items */
.menu {
    list-style: none;
    position: absolute;
    width: 100%;
    height: auto;
    top: 0;
    margin-top: var(--height-navbar);
    padding: 0 0 10px 0;
    clear: both;
    background: var(--background-navbar);
    transition: 0.3192s cubic-bezier(0.04, 0.04, 0.12, 0.96) 0.1008s;
    transform: scale(1, 0);
    transform-origin: top;
}

/* Hamburger menu button */
.menu-btn:checked~.menu {
    transform: scale(1, 1);
    transform-origin: top;
    transition: 0.3192s cubic-bezier(0.04, 0.04, 0.12, 0.96) 0.1008s;
}

/* Hamburger menbu text */
.menu a {
    text-decoration: none;
    font-weight: 500;
    letter-spacing: 2px;
    font-size: 16px;
    text-transform: capitalize;
    color: #ddd;
    opacity: 0;
    transition: 0.5s;
}

.menu li {
    border-top: 1px solid rgb(75, 75, 75);
    padding: 15px 0;
    margin: 0 54px;
    opacity: 0;
    transition: 0.5s;
}

.menu-btn:checked~.menu a,
.menu-btn:checked~.menu li {
    opacity: 1;
    transition: 0.3192s cubic-bezier(0.04, 0.04, 0.12, 0.96) 0.2s;
}

.menu-btn {
    display: none;
}

.menu-icon {
    display: inline-block;
    position: relative;
    cursor: pointer;
    padding: 24px 14px;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

.navicon {
    background: #ddd;
    display: block;
    height: 3px;
    width: 26px;
    position: relative;
    transition: 0.3192s cubic-bezier(0.04, 0.04, 0.12, 0.96) 0.1008s;
}

.navicon:before,
.navicon:after {
    content: "";
    display: block;
    height: 100%;
    width: 100%;
    position: absolute;
    background: #ddd;
    transition: 0.3192s cubic-bezier(0.04, 0.04, 0.12, 0.96) 0.1008s;
}

.navicon:before {
    top: 9px;
}

.navicon:after {
    bottom: 9px;
}

/* Hamburger Menu Animation Start */
.menu-btn:checked~.menu-icon .navicon:before {
    transform: rotate(-45deg);
}

.menu-btn:checked~.menu-icon .navicon:after {
    transform: rotate(45deg);
}

.menu-btn:checked~.menu-icon:not(.steps) .navicon:before {
    top: 0;
}

.menu-btn:checked~.menu-icon:not(.steps) .navicon:after {
    bottom: 0;
}

.menu-btn:checked~.menu-icon .navicon {
    background: rgba(0, 0, 0, 0);
    transition: 0.2192s cubic-bezier(0.04, 0.04, 0.12, 0.96) 0.1008s;
}

/* Hamburger Menu Animation End */

/* Navbar Container */
.navtext-container {
    width: 100%;
    height: var(--height-navbar);
    position: absolute;
    box-sizing: border-box;
    display: flex;
    justify-content: center;
    align-items: center;
}

/* Navbar Text */
.navtext {
    position: absolute;
    text-transform: uppercase;
    color: #ddd;
    letter-spacing: 4px;
    font-size: 20px;
}

main {
    padding-top: var(--height-navbar);
}
import { appRouter } from './pages/AppRouter';
import Home from './pages/Home';
import Page1 from './pages/Page1';
import Page2 from './pages/Page2';
// css 追加
import './App.css';

// ページ情報を定義して appRouter に設定
const pages = [
  { key: 'Home', path: '/', element: <Home /> },
  { key: 'Page1', path: '/page1', element: <Page1 /> },
  { key: 'Page2', path: '/page2', element: <Page2 text="text sample" /> },
];
const router = appRouter(pages);

const App = () => {
  return (
    <>
      {router.navbarLink}
      {/* 位置調整で main で括る */}
      <main>
        <h1>Hello World</h1>
        <p>App.jsx</p>
        {router.browserRouter}
      </main>
    </>
  );
};

export default App;
import { BrowserRouter, Routes, Route } from 'react-router-dom';

export const appRouter = (pages) => {
  const router = () => {
    return (
      <>
        <BrowserRouter basename={process.env.PUBLIC_URL}>
          <Routes>
            {pages.map((p) => (
              <Route key={p.key} path={p.path} element={p.element} />
            ))}
          </Routes>
        </BrowserRouter>
      </>
    );
  };
  // タグ, クラスなど追加
  const links = () => (
    <header className="header">
      <div className="navtext-container">
        <div className="navtext">title</div>
      </div>
      <input type="checkbox" className="menu-btn" id="menu-btn" />
      <label htmlFor="menu-btn" className="menu-icon">
        <span className="navicon"></span>
      </label>
      <ul className="menu">
        {pages.map((p) => (
          <li key={p.key}>
            <a href={`${process.env.PUBLIC_URL}${p.path}`}>{p.key}</a>
          </li>
        ))}
      </ul>
    </header>
  );
  return {
    browserRouter: router(),
    navbarLink: links(),
  };
};

如果以这种方式显示就可以了

image.png
广告
将在 10 秒后关闭
bannerAds