微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

day 1 react-router v6初使用

文章目录


前言

前端小菜鸟的研究第一天记录:昨天刚刚将使用脚手架初始化的一个空项目扔上去了,想着总这么空着不好,于是决定开始慢慢填充内容,主要是填充一些自己平时的学习内容,有个地方记录并呈现效果

1. 前期工作

(1)目录整理:目前的初始化的src文件目录比较杂乱,所以先按照开发习惯将src分了三个模块,分别是业务代码、静态资源和公共组件,目录层级看起来清爽了些。
(2)less- loader安装:因为看less比较习惯一点,所以将初始化时的css后缀全都改掉了,改完之后发现样式们都不生效了,研究了会发现是脚手架初始化出来的react项目不支持less,需要手动配置。
由于webpack配置上认隐藏的,所以首先通过npm run eject命令将其暴露如下图。
然后通过npm i less less-loader安装less和less-loader。
最后就是配置到webpack.config.js了。

# 1. 可以参照sass的格式并在其附近添加下面这两句,用于匹配less文件的处理
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;

# 2. 在getStyleLoaders函数中新增如下配置:
      {
        loader: require.resolve('less-loader')
      } 
                  
# 3. 在module.rules中新增如下配置,依旧可以参照sass:
 {
              test: lessRegex,
              exclude: lessModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 3,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                },
                'less-loader'
              ),
              sideEffects: true,
            },
         
            {
              test: lessModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 3,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                  modules: {
                    getLocalIdent: getCSSModuleLocalIdent,
                  },
                },
                'less-loader'
              ),
            },

这么一通搞下来就差不多了。

2. 主角来了

首页

大体的结构就是这样的,下面的tab是暂时两个,点击tab会跳往对应的路由,本来是想着没啥的,withrouter用一下,history push一下就过去了,结果跟我说没有withRouter这个东西,查了一下资料才知道v6版本已经取消这个了,所以又需要开始看一看了。。。

React Router库包含三个不同的npm包,以下每个包都有不同的用途。

  • react-router是核心库,用作另两个程序包的依赖
  • react-router-dom是React应用中用于路由的软件包
  • react-router-native用于开发React Native应用的绑定

2.1 路由创建

入口页面的路由创建如下,主要是从react-router-dom中导入了Routes、Route和HashRouter三个包。

import { Routes, Route, HashRouter as Router } from 'react-router-dom';
ReactDOM.render(
  <Router>
    <Routes>
      <Route exact path='/' element={<HomePage />} />
    </Routes>
  </Router>,
  document.getElementById('root')
);
  • Routes:相对于V5 版本的一个变化,之前是使用<switch />组件来做的,它包括相对路由和链接自动路由排名、嵌套路由和布局等功能
  • Route: 负责渲染React组件的UI,当匹配到path属性对应的url路径时渲染element对应的组件。与之前的<Route />相比,属性变化了,参数形式也变了。
  • HashRouter:实现全局路由的切换。
# 既然说到这里,顺便接一下HashRouter和browserRouter路由两者的区别:
1.browserHistory 使用的是H5的History API,浏览器提供相应的接口来修改浏览器的历史记录;
而 hashHistory 是通过改变地址后面的 hash 来改变浏览器的历史记录;

2. History API 提供了 pushState() 和 replaceState() 方法增加或替换历史记录。
hash 没有相应的方法,所以并没有替换历史记录的功能。(在hash模式下 ,history.push 底层是调用了window.location.href来改变路由。history.replace底层是掉用 window.location.replace改变路由。)

3. hash 部分不会被浏览器发送到服务端,也就是说不管是请求 http://domain.com/index.html#a 还是 http://domain.com/index.html#b ,服务只知道请求了 index.html 并不知道 hash 部分的细节。
而 History API 需要服务端支持,这样服务端能获取请求细节。

2.2 导航菜单添加

React程序中直接使用a标签进行页面跳转,将导致在每次渲染新视图或页面本身时刷新web页面。为了避免刷新网页,react-router-dom 库提供了 Link 组件大概的用法如下

<Router>
     <Link to="/" style={{ padding: 5 }}>
      Home
    </Link>
    <Routes>
      <Route exact path='/' element={<HomePage />} />
    </Routes>
  </Router>

方法也会将该标签处理为<a>,这样处理下点击对应的tab就会直接跳转到对应的组件,当然需要在上面的Routes中配置对应的路由信息。

function HomePage() {
  const tabs = [{
    id: 'homePage',
    text: <Link to='/'>首页</Link>
  }, {
    id: 'cssDemo',
    text: <Link to='/cssDemo'>CSS练手</Link>
  }];
  const [activeTab, setActiveTab] = useState('homePage');

  return (
    <div className="home-page">
      <header className="page-header">
        贝卡贝卡贝卡
      </header>
      <div className='home-body'>
        我还没想好放啥,将就看吧。。
      </div>
      <Tab tabs={tabs} activeTab={activeTab} setActiveTab={setActiveTab} />
    </div>
  );
}

2.3 嵌套路由处理

当路由被嵌套时,一般认为网页的某一部分保持不变,只有网页的子部分发生变化。
在React Router v5中,必须明确定义嵌套路由,React Router v6并非如此。它从React Router库中挑选了一个名为 Outlet 的最佳元素,为特定路由呈现任何匹配的子元素。
在我的Css练手页面中确实比较需要这样的场景,所以根据大佬的文章自己在这边尝试配置一下。

# 1. 在该页面中引入outlet,我理解这里类似于一个占位,等待匹配对应的路由
import React from 'react';
import { Outlet } from 'react-router-dom';

function CssDemo() {
    return (
        <div className="css-demo">
            <header className="demo-header">
                Css Demo
            </header>
            {/* 渲染任何匹配的子级 */}
            <Outlet />
        </div>
    );
}
export default CssDemo;

# 2. 列表组件如下:
function DemoList() {
    const demoPosts = {
        '1': {
            title: 'Demo 1',
            description: '练手学习的第一个css.'
        },
        '2': {
            title: 'Demo 2',
            description: '练手学习的第一个css'
        }
    };
    return (
        <div className="css-demo">
            {
                Object.entries(demoPosts).map(([slug, { title }]) => {
                    return <div key={slug}>
                        <span>{title}</span>
                    </div>
                })
            }
        </div>
    );
}

export default DemoList;
# 3.入口处添加如下配置
 <Route path='cssDemo' element={<CssDemo />} >
        <Route path="" element={<DemoList />} />  
 </Route>

效果展示如下图:

在这里插入图片描述

2.4 访问路由的URL参数和动态参数

列表的展示,已经初步实现了,接下来要做的便是点击对应的列表项能够进入对应的页面。将每个文章标题包裹在 DemoLists 组件中的 Link 组件内。然后,使用每个文章的 slug 定义每个文章的路径,前缀为 /cssDemo/ 的文章在浏览器中的路径是一致的。

 {
  Object.entries(demoPosts).map(([slug, { title }]) => {
       return <div key={slug}>
          <Link to={`/cssDemo/${slug}`}>{title}</Link>
           </div>
})
}

创建文章页

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

function Article() {
    const articles = {
        "1": {
          title: "第一篇博客文章",
          description: "第一篇哈哈哈哈"
        },
        "2": {
          title: "第二篇博客文章",
          description: "第二篇红红火火"
        }
      };
    
      const { slug } = useParams();
      const post = articles[slug];
      const { title, description } = post;
      return (
        <div className='article'>
          <h3>{title}</h3>
          <p>{description}</p>
        </div>
      );
} 

export default Article;

以上的路由使用操作,是根据这篇文章中的介绍来的,感觉很详细。
至此效果已基本达成,但还缺了一个重要的部分——返回

2.5 返回上一页

v5版本中的withRouter在v6中已被取消,取而代之的是更加方便的useNavigator钩子,具体的用法如下。

import React from 'react';
import { Outlet, useNavigate } from 'react-router-dom';
function CssDemo() {
    const navigate = useNavigate() 
    return (
        <div className="css-demo">
            <header className="demo-header" onClick={() => navigate(-1)}>
                Css Demo
            </header>
            <Outlet />
        </div>
    );
}

# 常见的几种用法如下
navigate('/homePage') 
navigate(-1) // 返回上一级
navigate(0, {replace: true})// 强制刷新当前页面并不加入路由历史

总结

以上就是V6的基本使用方法了,之后一阶段的主要目标就是加入node和数据库的操作实现更多的交互了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐