你好,我是王沛。今天我们来聊聊在React 开发过程中有哪些常用的第三方工具库。
如今的软件开发已经离不开开源社区提供的各类工具库了,合理的使用它们,不仅可以帮助节省重复的开发时间。而且通常来说,流行的开源库具有更充分的测试和更高的质量。因此,在 React 的开发过程中,知道 React 生态圈有哪些常用的工具库,了解它们能解决什么问题,是非常有必要的,我们要学会站在前人的肩膀上去成就自己嘛。
那么今天这节课,我会和你分享我自己最常用的四个工具库,分别是 lodash、Material UI、Ant.Design 和 react-use。我会通过一些例子来演示它们的部分功能和用法,让你对它们有一个总体的了解。
首先想和你分享的就是 lodash。在我看来,它是每一个前端开发者都应该熟练掌握的。
lodash 提供了非常多的工具函数,就像一把强大的瑞士军刀,能够满足各种前端开发需求,从而可以大大提高开发的效率。而且,lodash 不仅能用在浏览器端,也可以用在 NodeJS 的开发中。所以说,掌握了lodash ,也能提升 NodeJS 的开发效率。
下面我会通过三个短小的例子,来让你体会 lodash 带来的方便,这样我就不用给你解释什么叫惊喜了。
lodash 提供了大量操作数据结构的工具函数,其中 keyBy 是我最常用的方法之一。通常来说,我们从 API 会拿到数组存储的一组数据,为了对数据进行操作,我们一般需要根据数据的某个属性,快速找到数组元素,而 keyBy 可以帮助我们快速做到这一点。
比如,对于如下的数据结构:
const data = [
{
id: "1",
name: "Kennedy",
job: "Chief Mobility Orchestrator",
city: "North Alec",
},
{
id: "2",
name: "Lucius",
job: "Internal Research Manager",
city: "Littleland",
},
{
id: "3",
name: "Carlos",
job: "Lead Configuration Analyst",
city: "South Lillian",
},
]
如果要将其变成一个以 name 为 key 的 map 结构,那么只要用如下的代码就能完成。
import _ from 'lodash';
const byName = _.keyBy(data, 'name');
可以看到,一行代码就实现了这个转换,而且语义上也非常清楚。
在带有搜索框的页面里,我们通常会将搜索框的用户输入,保存为 searchKey 这样一个 state,当 searchKey 发生变化的时候去刷新搜索结果。但是,如果每次用户敲击一下键盘都去刷新搜索,其实是没有必要的,因为用户很可能还没有输入完关键字。而且,多余的搜索,还有可能会引起输入过程的卡顿。
为了解决这个问题,我们通常会使用防抖机制,也就是只有在用户停止输入后一个很短的时间内才进行搜索,比如说300毫秒,以保证更好的用户体验。而 lodash 就专门提供了 debouce 这样的一个函数。
它的用法如下:
import React, { useMemo } from "react";
import _ from "lodash";
import { useSearchParam } from "react-use";
function SearchBox({ data }) {
const searchKey = useSearchParam("key") || "";
const filtered = useMemo(() => {
return data.filter((item) =>
item.title.toLowerCase().includes(searchKey.toLowerCase()),
);
}, [searchKey, data]);
// 使用 _.debounce 处理用户输入,300ms 后才执行
const handleSearch = _.debounce((evt) => {
window.history.pushState(
{},
"",
`${window.location.pathname}?key=${evt.target.value}`,
);
}, 300);
return (
<div className="08-filter-list">
<h2>Movies (Debounced Search)</h2>
<input
defaultValue={searchKey}
placeholder="Search..."
onChange={handleSearch}
/>
<ul style={{ marginTop: 20 }}>
{filtered.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
</div>
);
在这里我们使用了lodash 的 debounce 方法封装了 handleSearch 这个事件处理函数,这样的话,就只有在停止输入300毫秒之后,才真正去执行搜索这个动作。
实际的效果你也可以参考在线的示例:https://codesandbox.io/s/react-hooks-course-20vzg 。
lodash 提供了一个简单的模板引擎,可以非常方便地让你去实现一些复杂的字符串生成。
比如下面就是一个例子:
var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
compiled({ 'users': ['fred', 'barney'] });
// => '<li>fred</li><li>barney</li>'
可以看到,_.template 通过一定的开始和结束标记,让你能够在其中使用条件判断、循环等功能。这在我们需要去生成类似 HTML、Markdown 等大段的文档时,就会非常有用。此外,将它作为一些样本代码的生成器,也是非常好用的。
当然,lodash 的功能远远不止于此,这里介绍的三个例子只是让你先对它有一个直观的了解和感受,更多的惊喜等待你自己去发掘。详细的 API 你可以去参考官方文档。
UI 组件库是前端开发必不可少的一部分,因此在开始开发 React 时,要做的第一件事大概就是选择UI库了。这里我主要介绍两个常用的 UI 库。
虽然 MUI 是基于 Google 的 Material Design,但是它提供了非常灵活的主题定制功能,这也是区别于 Ant Design 的一大特色。这就意味着基于 MUI 有一个庞大的主题市场,你可以从中选择自己需要的主题。
下图就是 MUI 官网提供的一些主题:
MUI 实现了一个强大的主题系统,主要原因就在于使用了 React Context 和 Styled Component 来实现 JavaScript 控制的动态主题系统,这也是它的基本原理。
比如下面这段代码,就展示了该如何定制一个主题:
import React from 'react';
import styled, { ThemeProvider } from 'styled-components';
import { createMuiTheme } from '@material-ui/core/styles';
import { palette, spacing, typography } from '@material-ui/system';
// 使用 JavaScript 定制样式
const Box = styled.div`${palette}${spacing}${typography}`;
const theme = createMuiTheme();
export default function Demo() {
return (
<ThemeProvider theme={theme}>
<Box
color="primary.main"
bgcolor="background.paper"
fontFamily="h6.fontFamily"
p={{ xs: 2, sm: 3, md: 4 }}
>
@material-ui/system
</Box>
</ThemeProvider>
);
}
这样,通过在你的组件中组合主题中定义的各种样式的规则,比如间距、字体、颜色等等,让你的组件就能够去适应各种不同的主题,从而保持 UI 样式的一致性。因此,如果你的应用对个性化的主题有比较高的需求,那么 Material UI 是不错的选择。
虽然 MUI 很酷炫,但它也有一个很大的缺点:组件库中缺少一些高级的功能。比如复杂的 Table、Tree 等,通常都需要依赖第三方来实现,而不是 MUI 自身就包含的。我们都知道,Table 和 Tree 是企业级应用最常用的组件。如果要依赖第三方,那质量和稳定性就参差不齐了。
那你可能就会问了,我到底该使用MUI还是AntD呢?我的一个标准是:要看你的应用是 To C 还是 To B。
如果是To C,就用 MUI,因为个性化的外观很重要。而如果是 To B,那就建议使用接下来要介绍的 AntD,因为它就是面向企业级应用设计的,风格以极简为主,组件库更丰富,功能也更强大。
Ant Design 在国内有很高的普及率,它使用 TypeScript 开发,提供了完整的类型系统;样式则是使用 Less 去实现。而且它的单元测试覆盖率超过 99%,因此功能非常稳定,这也是它能够得以普及的一个重要原因。
下图就显示了 AntD 提供的一个后台管理系统的模板:
AntD 的强大之处主要在于提供了各种高级组件,可以满足企业级的复杂交互应用场景。下面我对几个组件的特性进行一下简要的介绍,方便你有一个直观的了解:
当然,这些只是整个 AntD UI 库的一小部分功能,但我们已经可以看到它面向企业级应用的设计原则,它将重点放在了提供更多开箱即用的高级组件上,以提高开发效率。那么更完整的 API,你可以去参考官方文档。
在 React Hooks 推出之后,来自 React 开发社区的 Vadim Dalecky 将一些常用的需求封装成了可重用的 Hooks,方便了 React 的开发。这个就是 react-use 库,提供了各种的工具 Hooks,了解并熟练使用它们,可以节省很多重复的工作量。
下面就一起来看看我认为最为常用的四个 Hooks 吧:
其实在前面第8讲你已经看到了这个 Hook 的用法,就是用于获取 URL 中的查询字符串:
const searchKey = useSearchParam("key")
这样,你就能获得 key 这个参数的值,并且在值发生变化时触发组件的刷新。
如果用 DOM 的原生 API 去绑定事件,通常我们需要在组件创建时去监听,再在组件销毁时取消监听,比较繁琐。而 useEvent 这个 Hook 封装了这部分逻辑,让我们使用起来非常方便。
使用方法如下:
useEvent('keydown', onKeyDown);
这样的话,我们就可以在页面上监听键盘按键的事件,而无需关心该在何时绑定监听,以及何时取消监听。
Cookie 也是常用的数据源之一,但浏览器自带的 Cookie API 使用起来很不方便,需要自己去解析 Cookie 的值,而 useCookie 则可以让你很方便地去读取、更新或者删除某个 Cookie。
使用的方法如下:
const [value, updateCookie, deleteCookie] = useCookie("my-cookie");
需要注意的是,这里的 Hook 的作用域仅限于当前组件。如果 Cookie 是在组件外部被修改,则是无法触发当前组件的刷新的。你可以把这个Hook的作用看作是跟useState类似的,只是State 的值是持久化在 Cookie 里存储的。
这个 Hook 可以让你获取某个 State 的上一个值,有时我们需要比较前后值的变化,这时我们就能感受到usePrevious这个Hook的好用了。
使用的方法如下:
const [count, setCount] = React.useState(0);
// 获取 cound 的上一个值
const prevCount = usePrevious(count);
这节课我们主要介绍了 React 生态圈的四个常用工具库。主要的学习目的呢,就是为了让你对有助于 React 开发的重要项目做一个了解,从而避免在遇到一些需求时,自己费了很大力气去实现,却发现原来早有开源的方案。
这里尤其要强调的是 lodash。虽然它和 React 没有必然的关系,但是 lodash 非常擅长数据结构的各种转换,因此对React 中的状态管理非常有帮助。那么熟悉它的API,自然也是非常有必要的。
虽然这节课我只介绍了几个工具库,但是整个开源生态是非常庞大的,你在开发过程中也一定会去使用各种开源的项目。那么在这里我也和你分享一下开源项目选择的几个考虑因素。
总之呢,开源社区是一个大宝藏,有很多很好的项目等待着你去发掘。
文中主要分享了我个人一直使用的工具库,你有什么觉得用着非常顺手的工具库呢?和大家分享一下吧,说说它们给你带来的惊喜。
欢迎把你的想法和思考分享在留言区,我会和你交流讨论。也欢迎把课程分享给你的朋友和同事,大家共同进步。