首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >『Dva』路由

『Dva』路由

原创
作者头像
程序员NEO
修改2024-12-02 07:34:53
修改2024-12-02 07:34:53
20400
代码可运行
举报
运行总次数:0
代码可运行

推荐文章

简介

链接

🌍从 MVC 到微服务:架构演化的历程与应用场景(含代码演示)

这篇文章是技术深度文章,作者详细阐述了从MVC架构到微服务架构的演化过程,并结合具体的代码示例,展示了不同架构的设计思想和实现逻辑。

一、前言

🐤本篇文章是『从零玩转 TypeScript + React 项目实战』系列文章的第 7 篇,主要介绍『Dva』中的订阅

经上一篇『Dva』订阅,文章介绍,了解了下 Model 当中的 Subscription 也就是所谓的订阅,到此我们也掌握了如何通过 Dva 来管理数据。

那么本篇文章呢,我就来继续介绍下在 dva 中如何使用路由。

二、Dva 中的路由

2.1 搭建使用路由环境(新增多个组件)

在 dva 中如何使用路由呢?要想使用路由,要想看到路由的效果的话,首先,是不是要先多搞几个组建,对吧?

所以我就不管三七二十一,我在定义一个 about 组件,再定义一个 aboutModel 保存一下 about 组件的数据,然后呢代码如下,先是定义 aboutModel,aboutModel 的命名空间呢叫 about,aboutModel 保存了一个 count,aboutModel 有自己的 Reducers,aboutModel 自己的 Reducers 有两个方法可以对 count 进行增加和减少的操作。

这个 aboutModel 内容大致就这些,代码如下:

代码语言:javascript
代码运行次数:0
运行
复制
let aboutModel = {
    namespace: 'about',
    state: {
        count: 123
    },
    reducers: {
        add: (state, action) => {
            return {
                count: state.count + action.count
            }
        },
        sub: (state, action) => {
            return {
                count: state.count - action.count
            }
        }
    }
}

定义好 aboutModel 之后呢,是不是还要告诉 dva,我需要使用这个 aboutModel:

代码语言:javascript
代码运行次数:0
运行
复制
app.model(aboutModel);

告诉 dva 要使用 aboutModel,我是不是还要将 aboutModel 当中的数据和方法映射到 about 组件中去,这个时候呢,我直接将 home 组件的内容拷贝一份改吧改吧。

About:

代码语言:javascript
代码运行次数:0
运行
复制
function About(props) {
    return (
        <div>
            <p>{props.count}</p>
            <button onClick={() => {
                props.increment()
            }}>+
            </button>
            <button onClick={() => {
                props.decrement()
            }}>-
            </button>
        </div>
    )
}

About 组件呢,分别做了展示和方法调用的操作,从映射的数据当中拿到映射的 count 进行了展示,在分别调用了映射的 incrementdecrement 方法。

接下来是不是就要来映射一下,通过 saga 的 connect 方法来映射,映射之前我还需要处理一下映射,编写 mapStateToProps 方法来映射,这次我要映射的数据名称为 count,这个 count 从哪来,是不是从命名空间为 about 的这个 Model 中获取。

为了防止 mapStateToProps 与 home 的 mapStateToProps 名称重复我这里定义为叫 mapStateToPropsAbout

代码语言:javascript
代码运行次数:0
运行
复制
const mapStateToPropsAbout = (state) => {
    return {
        // 需要从传入的 state 的命名空间中拿到对应 Model 保存的数据
        count: state.about.count,
    }
};

数据映射完成之后,再来看派发任务,一样的拷贝一下之前的 mapDispatchToProps,之前编写的 mapDispatchToProps 是针对于 home 的,但这次是给 about 进行映射,所以也是一样为了防止 mapDispatchToProps 与 home 的 mapDispatchToProps 名称重复我这里定义为叫 mapDispatchToPropsAbout

不过目前都是派发到 home 当中,现在是不是要派发到 about,所以更改一下,并且告诉它我要修改的是 count,为了区分 home 与 about 的增加与减少呢,这里我给它设置的传参为 2:

代码语言:javascript
代码运行次数:0
运行
复制
const mapDispatchToPropsAbout = (dispatch) => {
    return {
        increment() {
            dispatch({type: 'about/add', count: 2});
        },
        decrement() {
            dispatch({type: 'about/sub', count: 2});
        }
    }
};

mapStateToPropsAbout,mapDispatchToPropsAbout 都处理编写好了之后,是不是基本大概差不多就搞定了,最后再通过 connect 连接到 about 组件上去,这样就完成了一次 about 组件的映射。

代码语言:javascript
代码运行次数:0
运行
复制
const AdvAbout = connect(mapStateToPropsAbout, mapDispatchToPropsAbout)(About);

接下来就可以在 app 中使用 about 了,来到 app 组件代码中使用 about,为了能看出效果我弄了一个 hr 标签,分割一下:

运行项目,浏览器查看:

将之前的异步数据处理的代码可以先注释掉或者可以删掉,本次就关注 home 与 about 的内容,Home 组件就只留如下图代码即可:

home 的 +、- 增值是 1,about 是 2:

有了多个组件,就可以利用本次文章要介绍的路由来切换组件了,利用路由切换组件怎么切换呢,也非常的简单,在 dva 中它对路由进行了一个简单的封装。

2.2 使用路由

要想使用它就得要先导入 dva 封装好的路由,从哪导入呢,从 dva 的 router 当中导入,我这里采用解构的方式解构出想要的内容,在 dva router 中,它给我们封装好了一个 Router 与 Route:

代码语言:javascript
代码运行次数:0
运行
复制
import { Router, Route } from 'dva/router'

接下来就可以使用了,找到 app,我先将 app 过去的代码全部干掉,或者可以进行注释,那么就注释掉吧,保留下,还是还是删除掉吧,反正我进行了项目 Git 管理,就不会有这样的问题了。然后我在 app 中首先放上一个 Router:

代码语言:javascript
代码运行次数:0
运行
复制
function App() {
    return (
        <Router>
        </Router>
    );
}

因为 Router 里面呢只能有一个根,所以我就在 Router 中放上一个 Fragment(对 Fragment 不清楚的请查看:https://zh-hans.react.dev/reference/react/Fragment),放完 Fragment 之后我然后再 Fragment 中放上一个 Route:

代码语言:javascript
代码运行次数:0
运行
复制
function App() {
    return (
        <Router>
            <>
                <Route></Route>
            </>
        </Router>
    );
}

在 Route 中可以通过 path 可以告诉它匹配哪一个地址,我这里就将这个 Route path 设置为 home,然后呢在 Route 中还有一个 component,这个 component 意思是如果是 home 就要渲染哪一个组件,我这里渲染 AdvHome:

About 也是同理可证:

代码语言:javascript
代码运行次数:0
运行
复制
<Route path={'/home'} component={AdvHome}/>
<Route path={'/about'} component={AdvAbout}/>

好,基本上代码写完了,回到网页当中刷新一下,不出意外的话应该是会报错:

为什么会报错呢?如果说回顾一下过去在使用 React Router 的时候是不是区分模式,那么区分什么模式呢,是不是区分 history 和 hash 模式,但现在我使用的是 dva 给我们封装好的 Router 的时候,是不是并没有告诉 Router 是什么模式的。

怎么告诉 Router 是什么模式,这个时候就需要从创建 dva 实例这行代码说了,这里也是本次要说的注意点。

2.3 注意点

  • 我们在通过 dva 方法创建 dva 实例的时候,这个方法是可以接收一个对象的
  • 我们可以在这个对象中指定 dva 路由的模式
  • 如果在创建 dva 实例的时候,没有指定路由的模式,那么默认就是 hash 模式。

2.4 hash

那么如上这些我是怎么知道的呢?非常的简单,回到 dva 的官方文档,找到 API,然后找到创建 dva 实例的文档说明:https://dvajs.xiniushu.com/api/#app-dva-opts

经过观察,dva(opts),是不是说明了接收一个参数名为 opts 的内容,opts 是什么是不是一个对象:

可以通过该对象的 history 修改模式,官方也为 history 做了说明,history:指定给路由用的 history,默认是 hashHistory,经过这样的解释之后是不是就验证了我的说法。

好,验证了我的说法之后还没完,既然它默认是 hash,那为什么它还会报错呢?原因很简单,默认是 hash 但是我没有告诉 Router 就要使用 hash 模式,那怎么告诉 Router 就要使用 hash 模式呢?

也很简单,继续看官方文档找到 app.router 的方法文档,也就是 dva 的 router 文档:

过去我们是不是在代码中通过 router 将来我要渲染哪个组件,如下这段代码:

其实在告诉 dva router 渲染哪个组件的时候,还可以做一件事情,这个时候回到文档,发现它代码中通过解构的方式解构出来了一个 history,说明什么,说明在渲染的时候会给这个函数传参:

所以说,我代码也可以通过这种方式解构出来 history,也就是当前的模式:

再通过如上我所说的,如果没有指定那么就是默认为 hash 模式,如果指定了这个解构出来的就是你指定的那个模式,总结说一下就是,dva 的 router 方法在执行回调函数的时候会传递一个对象给我们,我们可以从这个对象中解构出当前理由模式。

如果在创建 dva 实例的时候,没有指定模式,那么得到的就是 hash 模式,如果在创建 dva 实例的时候指定了模式,那么得到的就是我们指定的模式。

我代码中通过 dva 创建的时候是不是没有指定模式,那么 app.router(({history}) => <App/>); 这里的 history 就是 hash,拿到了当前的模式之后呢,我是不是可以直接将该模式传递给我的 app 组件:

代码语言:javascript
代码运行次数:0
运行
复制
app.router(({history}) => <App history={history}/>);

在 app 组件当中通过 props 接收一下,接收到了之后再通过 Router 中的 history 属性告诉 Router 是什么模式:

代码语言:javascript
代码运行次数:0
运行
复制
function App(props) {
    return (
        <Router history={props.history}>
            <>
                <Route path={'/home'} component={AdvHome}/>
                <Route path={'/about'} component={AdvAbout}/>
            </>
        </Router>
    );
}

现在使用的是 hash 模式,前说过了,这些内容我都是怎么知道的我都是从文档里面抄的,官方文档也是解构当前的模式,然后将模式告诉 Router:

回到网页刷新一下,就不会报错了,路径地址后面有一个 # 号,是不是意味着当前是 hash 模式,如果我在当前的地址后面输入 home 是不是应该切换到 home:

访问 about 是同理可证的,不测试了,那么这个使用我不想使用 hash 了,该怎么办?

2.5 history

我想使用 history,这个时候怎么做呢?是不是还是回到官方文档当中找到创建 dva 实例对象的代码,已经告诉我们如何操作了,首先得要导入 createHistory 这个方法:

代码语言:javascript
代码运行次数:0
运行
复制
import createHistory from 'history/createBrowserHistory';

然后再代码中创建 dva 实例的时候传递一个对象,通过对象的 history 属性来告诉 dva Router 使用什么路由模式,告诉它我修改路由模式为我指定的:

代码语言:javascript
代码运行次数:0
运行
复制
const app = dva({
    history: createHistory()
});

如上代码的意思就是我修改了 dva 的理由模式,修改为了 history 模式,修改完之后,我利用 hash 的方式访问,会发现页面访问不出来了:

为什么呢?是不是因为路径地址中有 # 号,就是因为我修改了 dva 的路由模式,history 模式是没有 # 号的,把 # 号去掉直接输入 home:

访问 about 同理可证的,不测试了,好了如上内容就是在 dva 中如何使用路由,以及呢如何指定路由模式。

三、总结

通过本文的学习,您可以掌握以下知识点:

  • 1.Dva 路由的基本使用:如何在 Dva 中定义多个组件及其对应的 Model。使用 connect 将 Model 的状态和方法映射到组件中,实现组件数据的动态更新。
  • 2.Dva 路由环境的搭建:利用 RouterRoute 实现不同路径对应不同组件的渲染。通过 path 属性指定路由路径,component 属性指定渲染组件。
  • 3.Dva 路由模式的配置:Dva 默认支持两种路由模式:hashhistory。在创建 Dva 实例时,可以通过 history 属性指定路由模式。
  • 4.常见问题与解决方案:当未正确设置路由模式时,可能会导致页面报错,通过阅读官方文档了解问题来源并修复。配置路由模式时需要结合 app.routerRouterhistory 属性,实现一致性。
  • 5.学会查阅官方文档:通过 Dva 官方文档快速了解 API 使用方式和参数设置。

🐤如果您觉得本文对您有所帮助,欢迎点赞、收藏或分享,您的支持是我创作的最大动力!

这篇文章的内容就介绍到这里,期待我们下次的相遇。感谢您花时间阅读,如果有任何问题或想法,欢迎在评论区留言。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言
  • 二、Dva 中的路由
    • 2.1 搭建使用路由环境(新增多个组件)
    • 2.2 使用路由
    • 2.3 注意点
    • 2.4 hash
    • 2.5 history
  • 三、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档