IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> React router: 构建多页的 SPA -> 正文阅读

[JavaScript知识库]React router: 构建多页的 SPA

使用 Router 可以构建多页的 Single-Page App

1 安装 react router :

npm intall react-router-dom

2 基本用法

2.1 App.js 导入Route 组件

import { Route } from "react-router-dom";

2.2 App.js 定义路径:

共两条路径:

http://localhost:3000/welcome
http://localhost:3000/products

不同的路径加载相对应的组件。

// import Route from the library
import { Route } from "react-router-dom";
import Welcome from "./components/Welcome";
import Products from "./components/Products";

function App() {
  return (
    <div>
      <Route path="/welcome">
        <Welcome />
      </Route>
      <Route path="/products">
        <Products />
      </Route>
    </div>
  );
}

export default App;

2.3 index.js 代码:

import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";

import "./index.css";
import App from "./App";

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById("root")
);

由于Welcome.js 和 Products.js 是与route 相关的组件,比起src/components,把它们放在名称为src/pages的文件夹中更恰当。

3 添加页面链接

3.1 标准链接方式,使用 <a> 实现页面导航。

此方法有一个缺点:每次点击链接,页面都会重新加载,App 重启,因此会丢失当前状态。

// MainHeader.js
const MainHeader = () => {
  return (
    <header>
      <nav>
        <ul>
          <li>
            <a href="/welcome">Welcome</a>
          </li>
          <li>
            <a href="/products">Products</a>
          </li>
        </ul>
      </nav>
    </header>
  );
};
export default MainHeader;
// App.js 
function App() {
  return (
    <div>
      <MainHeader />
      <main>
        <Route path="/welcome">
          <Welcome />
        </Route>
        <Route path="/products">
          <Products />
        </Route>
      </main>
    </div>
  );
}

3.2 使用 react-router-domLink 组件

<a> 改成 <Link> ,然后href 改成 to,如下的代码将阻止浏览器默认行为,页面不会重新加载:

import { Link } from "react-router-dom";
const MainHeader = () => {
  return (
    <header>
      <nav>
        <ul>
          <li>
            <Link to="/welcome">Welcome</Link>
          </li>
          <li>
            <Link to="/products">Products</Link>
          </li>
        </ul>
      </nav>
    </header>
  );
};

export default MainHeader;

3.3 NavLinkactiveClassName

使用 Link 组件虽然能避免页面重新加载,但是,用户无法直接看出当前点击了哪一个链接。
Link 改成 NavLink 就能使用 activeClassName 对当前链接添加 CSS 样式,对链接进行样式设定,

import { NavLink } from "react-router-dom";
import classes from "./MainHeader.module.css";
const MainHeader = () => {
  return (
    <header className={classes.header}>
      <nav>
        <ul>
          <li>
            <NavLink activeClassName={classes.active} to="/welcome">
              Welcome
            </NavLink>
          </li>
          <li>
            <NavLink activeClassName={classes.active} to="/products">
              Products
            </NavLink>
          </li>
        </ul>
      </nav>
    </header>
  );
};
export default MainHeader;
// MainHeader.module.css
.header {
  width: 100%;
  height: 5rem;
  background-color: #044599;
  padding: 0 10%;
}

.header nav {
  height: 100%;
}

.header ul {
  height: 100%;
  list-style: none;
  display: flex;
  padding: 0;
  margin: 0;
  align-items: center;
  justify-content: center;
}

.header li {
  margin: 0 1rem;
  width: 5rem;
}

.header a {
  color: white;
  text-decoration: none;
}

.header a:hover,
.header a:active,
.header a.active {
  color: #95bcf0;
  padding-bottom: 0.25rem;
  border-bottom: 4px solid #95bcf0;
}

4 动态路由

4.1 注册带参数的动态路由

例如,要添加一系列 products 的详情页:

冒号必须加,

   <Route path="/product-detail/:productId">
      <ProductDetail />
    </Route>

:productId 是占位符,是 dynamic segment
此语法告诉 React Router, 为路径:

ourdomain.com/product-detail/ <any thing...>

加载 <ProductDetail /> 页面

4.2 使用 useParams 提取动态参数

钩子函数 useParams 返回一个key value对组成的对象,key 是动态路径的参数名。

注册路径:<Route path="/product-detail/:productId">
输入路径 : localhost:3000/product-detail/product1
params.productId 的值为 product1

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

const ProductDetail = () => {
  const params = useParams();
  return (
    <section>
      <h1>Product Detail</h1>
      <p>{params.productId}</p>
    </section>
  );
};
export default ProductDetail;

5 使用 switchexact 配置路由

当前的问题,默认加载 全部 匹配输入路径的路由:

function App() {
  return (
    <div>
      <MainHeader />
      <main>
        <Route path="/welcome">
          <Welcome />
        </Route>
        <Route path="/products">
          <Products />
        </Route>
        <Route path="/products/:productId">
          <ProductDetail />
        </Route>
      </main>
    </div>
  );
}

例如:

http://localhost:3000/products/p2

此路径匹配两个路由: /products/products/:productId 因此同时加载 两个 页面。
/products/:productId/products 开头,所以匹配两个路径,与路由注册前后顺序无关。同时加载多个页面,有时,这是期望的行为,有时则不是,没有对错之分。

5.1 使用 Switch 组件实现唯一匹配

Switch 组件保证一个路径只加载一个路由,并且是 第1个 相匹配的路由:
按照以下的 Route 注册顺序, /products/:productId 不会被加载,因为是第2个匹配到的路由,只有第1个匹配的路由:/products 被加载。
(至少 React Router 5 的行为是这样)

import { Route, Switch } from "react-router-dom";
import Welcome from "./pages/Welcome";
import Products from "./pages/Products";
import MainHeader from "./components/MainHeader";
import ProductDetail from "./pages/ProductDetail";

function App() {
  return (
    <div>
      <MainHeader />
      <main>
        <Switch>
          <Route path="/welcome">
            <Welcome />
          </Route>
          <Route path="/products">
            <Products />
          </Route>
          <Route path="/products/:productId">
            <ProductDetail />
          </Route>
        </Switch>
      </main>
    </div>
  );
}
export default App;

5.2 exact 属性

为了解决上述 /products/:productId 不会被加载的问题,有两个 solution:

5.2.1 调整路由顺序

例如,调用两个匹配的路由的上下顺序:
因此 /products/p1 将匹配/products/:productId而不是 /products

<Route path="/products/:productId">
	<ProductDetail />
</Route>
<Route path="/products">
	<Products />
</Route>

5.2.2 使用 exact 属性实现精确匹配

保持原始路由顺序不变,特定的路由添加 exact 属性,告诉 react router,当且仅当路径 完全匹配 时匹配路由。

下面的 code,/products/xyz 不再匹配 /products/:productId

function App() {
  return (
    <div>
      <MainHeader />
      <main>
        <Switch>
          <Route path="/welcome">
            <Welcome />
          </Route>
          <Route path="/products" exact>
            <Products />
          </Route>
          <Route path="/products/:productId">
            <ProductDetail />
          </Route>
        </Switch>
      </main>
    </div>
  );
}

6 嵌套路由

App.js 并非唯一可以设置路由的组件。路由也可以设置路由,所有的组件都可以添加路由:例如:

// Welcome.js
import { Route } from "react-router-dom";
const Welcome = () => {
  return (
    <section>
      <h1>The welcome page</h1>
      <Route path="/welcome/new-user">
        <p>Welcome, new user!</p>
      </Route>
    </section>
  );
};
export default Welcome;

7 使用 Redirect 组件实现重定向

下面的例子,如果用户输入/ 自动重定向到路由 /welcome, <Route path="/" exact>exact 属性很重要,因为 / 匹配任意路由,没有此属性会无限循环。

import { Route, Switch, Redirect } from "react-router-dom";
import Welcome from "./pages/Welcome";
import Products from "./pages/Products";
import MainHeader from "./components/MainHeader";
import ProductDetail from "./pages/ProductDetail";

function App() {
  return (
    <div>
      <MainHeader />
      <main>
        <Switch>
          <Route path="/" exact>
            <Redirect to="/welcome" />
          </Route>
          <Route path="/welcome">
            <Welcome />
          </Route>
          <Route path="/products" exact>
            <Products />
          </Route>
          <Route path="/products/:productId">
            <ProductDetail />
          </Route>
        </Switch>
      </main>
    </div>
  );
}
export default App;
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-30 18:50:47  更:2022-01-30 18:52:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 13:46:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码