005 优雅的在 umi 页面间穿梭

简介: 005 优雅的在 umi 页面间穿梭

image.png

这节课我们主要学习如何通过声明式和命令式的方式实现客户端页面间的导航。并运用 React Route 6 的 API 获取路由上的信息。

上一节课之后,我们已经有了两个页面,首页和用户页面,这节课我们将在首页使用声明式方式跳转到用户页面,然后在用户页面使用命令式跳转到首页。



声明式

在网站的页面之间链接时,你通常使用 <a> HTML 标签。

在 Umi 中,你使用了从 umi 导出的 <Link> 组件对应用程序中的不同页面进行客户端导航。


首先,在 pages/index.js 中,从 umi 导入 Link 组件,方法是在顶部添加这一行:

import { Link } from 'umi';
复制代码


然后修改 div 标记中的这一行:

Index Page
复制代码


修改为:

import { Link } from 'umi';
export default () => <div>Index Page
    <p><Link to="/user">Go to user page</Link></p>
</div>;
复制代码



命令式(history、useNavigate)

上述内容,我们在首页使用声明式的方法添加了一个跳转到 user 页面的方法,接下来我们通过命令式的方式,从 user 返回首页。


接下来,将 pages/user/index.js 的内容改为:

import { history, useNavigate } from 'umi';
export default function User() {
    const navigate = useNavigate();
    return (
        <div>
            <h1>User Page</h1>
            <button onClick={() => history.back()}>go back by history!</button>
            <button onClick={() => history.push('/')}>go to index by history!</button>
            <button onClick={() => navigate(-1)}>go back by navigate!</button>
            <button onClick={() => navigate('/')}>go to index by navigate!</button>
        </div>
    );
}
复制代码

上面的页面中,我们增加了四个按钮,使用 historyuseNavigate 分别实现了回退方法,和页面跳转方法到达首页。


虽然从效果是来看都是从列表页跳转到了主页,但需要注意的是,使用 back 方法,会撤回一次浏览器历史。也就是说,你无法使用浏览器上面的后退按钮(包括安卓设备上的返回键),返回 user 页面。而使用 push 返回,会增加一个浏览器历史。如果多次在两个页面之间 push ,会导致使用回退按钮返回页面时,会有一个很长的浏览器历史列表。


back 方法完全依赖于项目的浏览历史,也就是说完全依赖于你的“前一个页面”。这意味着,当你在当前路由刷新页面时, back 有可能会失效。所以实际项目中,要根据具体的项目逻辑和场景来选择合适的方法。


虽然命令式 historyuseNavigate 看起来都可以实现在页面之间导航,但是需要注意的是 useNavigate 只能用在 React 存在的上下文中,简单的说就是他只能在组件的生命周期中使用,如果你在全局的文件,比如 app.ts 或者 global.ts 文件中就不能使用 useNavigate ,只能使用 history



使用 url 传参(SearchParams)

url 传参就是 url 中的 search 对象,来进行页面之间的参数传递,是一种特别常用的前端传参手段,就是我们经常看到 url 中带有一个 ? 后面跟着一些 xx=yy&&dd=mm 之类的字符。 我们可以在页面中取出它们来进行页面逻辑编写。


首先我们介绍一下 Umi 中如何取到 url 中的参数。

import { useSearchParams } from 'umi';
export default () => {
    const [searchParams, setSearchParams] = useSearchParams();
    const a = searchParams.get('a');
    const b = searchParams.get('b');
    return <div>
        <p>SearchParams ---- a:{a};b:{b}</p>
    </div>
};
复制代码

我们使用 useSearchParams 来取到 url 中携带的参数,用法非常的便捷。 有读数据,当然也有写数据操作。



刷新 SearchParams

可以分为两种情况,当前页面可以使用 useSearchParams 返回的第二参数,刷新 SearchParams

import { Link, useSearchParams, createSearchParams } from 'umi';
export default () => {
    const [searchParams, setSearchParams] = useSearchParams();
    const a = searchParams.get('a');
    const b = searchParams.get('b');
    return <div>
        <p>SearchParams ---- a:{a};b:{b}</p>
        <button onClick={() => {
            setSearchParams(createSearchParams({ a: 123, b: 456 }));
        }}>Change SearchParams</button>
    </div>
};
复制代码



写入 SearchParams

第二种情况是从别的页面跳转的时候携带 SearchParams

import { useNavigate, createSearchParams } from 'umi';
export default function User() {
    const navigate = useNavigate();
    return (
        <div>
            <button onClick={() => {
                navigate(`/?${createSearchParams({ a: 1, b: 2 })}`)
            }}>go to index has SearchParams!</button>
        </div>
    );
}
复制代码


操作 SearchParams 我们都可以通过 Umi 提供的 createSearchParams API 来很轻松的完成。

使用 SearchParams 最大的好处就是数据永久化,只要你将完整的链接发送给用户,那链接中都将会携带这些参数。坏处就是,参数都是显示存在的,对于一些安全性场景的敏感数据,可能太不友好。所以我们可以使用另外一种隐蔽性更强的方式实现参数传递。



Route State

import { useNavigate } from 'umi';
export default function User() {
    const navigate = useNavigate();
    return (
        <div>
            <button onClick={() => {
                navigate('/', {
                    state: {
                        c: 987
                    }
                })
            }}>go to index has State!</button>
        </div>
    );
}
复制代码


在首页可以在 location 对象中取到 State,这个和 React 中的 State 类似,只不过它是一个临时性的数据,当你在全新的环境打开这个链接,将会丢失这个数据。

可以使用 useLocation 获取到 location

import { useLocation } from 'umi';
export default () => {
    const location = useLocation();
    return <div>
        <p>State ---- {location.state}</p>
    </div>
};
复制代码


两种参数传递的方式,都有自己的利弊,分别应对不用的项目交付场景,在真实的项目中可以充分分析需求,权衡利弊来使用不同的方式。


当然以上提到的两种方式,是纯路由传参的手段,我们也可以通过前端数据流的方式来实现参数传递。当需要传递一个比较大的对象时,还可以借助服务端的能力,将数据保存到服务端,到新页面再通过接口获取。


源码归档

目录
相关文章
|
10月前
|
JavaScript
Vue打包后页面出现空白解决办法(臻享版)
1. 命令行输入:**npm run build** 打包出来后项目中就会多了一个文件夹dist,这就是我们打包过后的项目。
470 1
|
1天前
|
前端开发
React 仿淘宝图片放大镜功能
React 仿淘宝图片放大镜功能
|
9月前
|
前端开发 JavaScript
【React工作记录八十】 一步步教你用taro封装一个公司库的下拉组件
【React工作记录八十】 一步步教你用taro封装一个公司库的下拉组件
61 0
|
1天前
Vuetify 明暗主题切换
Vuetify 明暗主题切换
|
1天前
|
JavaScript 前端开发
使用styled-components控制主题切换(有手就行)
使用styled-components控制主题切换(有手就行)
|
10月前
|
JavaScript 前端开发 搜索推荐
一次Vue改版多标签页的实录
一次Vue改版多标签页的实录
222 0
|
JavaScript 前端开发
vue开发后打包部署的网站页面变灰色
vue开发后打包部署的网站页面变灰色
198 0
|
自然语言处理 JavaScript 前端开发
ElementUI在实际项目使用的功能总结
ElementUI在实际项目使用的功能总结
ElementUI在实际项目使用的功能总结
|
JavaScript 前端开发
哈~这个vue3组件库中的组件真的是超多,不来试试吗?
随着vue在国内的越来越火,也应运而生了很多的优秀的UI组件库。都很有特点,也比较好用。如大家都能耳熟能详的 element-ui 和 Ant Design Vue都是非常不错的。可惜的是 element-ui 不再维护升级vue3了,不过它的继任者 element-plus确实正在如火如荼的开发着,支持vue3。喜欢 element-ui的一定不要错过它。
哈~这个vue3组件库中的组件真的是超多,不来试试吗?
|
前端开发
react实战笔记95:添加checkout组件2结账页面
react实战笔记95:添加checkout组件2结账页面
71 0
react实战笔记95:添加checkout组件2结账页面