读开源项目《antd-design》源代码第一天

今天开始仔细阅读《antd-design》源码,首先看了源码部分的components中的button,本身就知道它一定很有难度,所以刚开始就选择了我认为较简单的button部分,在本地把项目跑起来后,进入到 button 页面,再仔细观看源码部分,我有点吃惊,仿佛打开了新的认知。


组件页面的每个小例子竟然都是一篇独立的markdown,通过多篇markdown组成了一整个页面。一方面认识到原来markdown还可以这么用,之前还一直很好奇把这么多例子写在每个页面中,代码一定特别繁琐,这样看来,果真是我太小白了。

接着我开始仔细翻阅button中的主要代码。第一遍我先把整页代码过了一遍,看看能不能读清楚然后将它完整的理解下来,结果我发现了许多不认识的方法函数!因此我开始慢速的读第二遍,开始记录一些我不清楚的点,主要分为两方面:1. 之前没见到过的。2. 眼熟但是已经记不清楚用法的地方。

记录未明白的地方

项目结构

我大概看了一下项目结构,起初我认为每个组件是一个独立的页面所构成的。但是我看到button文件的代码中,还有许多的逻辑,和数据的类型分类。因此我猜想整体的页面可能就只有首页、组件页、文档页这类,所有的组件应该是复用了一套逻辑,既然我现在要看组件页,那这里的代码一定是各个按钮如何构成并且通过这些复杂的逻辑来实现的。想明白这些,我开始耐心的去看每一行代码。(在最近的学习与探索过程中,我发现在学习新的东西的时候,刚开始一定会有许多许多不认识、不明白的地方。这种时候更加不可心急,反而更应该耐下心来,一点一点看,一点一点的去分析去理解。)

从代码中学习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const rxTwoCNChar = /^[\u4e00-\u9fa5]{2}$/;
const isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar);
function isString(str: any) {
return typeof str === 'string';
}

function isUnborderedButtonType(type: ButtonType | undefined) {
return type === 'text' || type === 'link';
}
// Insert one space between two chinese characters automatically.
function insertSpace(child: React.ReactChild, needInserted: boolean) {
// Check the child if is undefined or null.
if (child == null) {
return;
}
const SPACE = needInserted ? ' ' : '';
// strictNullChecks oops.
if (
typeof child !== 'string' &&
typeof child !== 'number' &&
isString(child.type) &&
isTwoCNChar(child.props.children)
) {
return cloneElement(child, {
children: child.props.children.split('').join(SPACE),
});
}
if (typeof child === 'string') {
if (isTwoCNChar(child)) {
child = child.split('').join(SPACE);
}
return <span>{child}</span>;
}
return child;
}

在代码的开头我就开始不明白了。我首先查询了rxTwoCnchar的声明,然后明白这些是强大的正则匹配,和jQuery的知识!查过之后才明白,这里是用 jQuery 为文本绑定了一个方法:用正则匹配将每个字符串都分隔开,为之后给每个字体中间加空格做准备。

jQuery:

  1. .text: 设置或返回所选元素的文本内容。

  2. .bind: 绑定事件,为所选元素添加一个或者多个事件处理程序,以及当事件发生时运行的函数。

接着我又查询了splitjoin的用法。之前一直以为它们只在 JS 中有,一查发现在 Python 中也要这两种方法。

  1. split是 Python 中通过制定分隔符对字符串进行切片,如果有 num ,则代表分隔 num +1 个字符串。
  2. join是 SQL 中的连接,我将它理解为数学中多个集合的交集的结果,根据需要取不同的结果部分,就是将符合join中的所有条件的值都组合起来。

接着往下读代码又认识了一个 React 的一个克隆 API:cloneElement,此 API 以 element 元素为样板克隆并且返回新的 React 元素,注意:新的子元素将取代现有的子元素,而来自原始的元素的 key 和 ref 将被保留。

React.cloneElement()几乎等同于:

1
<element.type {...element.props} {...props}>{children}</element.type>

useContext

之前已经看到了 React 中几个常用 Hooks 的讲解和用法,它突然出现的时候我对此 Hook 已经不记得它的具体用法,因此我把它重新回顾学习了一下并且在这里记录下来。

1
const value = useContext(MyContext);

介绍:该 Hook 接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的 <Mycontext.Provider>的 value prop 决定。

当组件上层中最近的 <Mycontext.Provider>更新时,该 Hook 会触发重新渲染,并使用最新传递个 Mycontext provider 的 context value 值。即使祖先使用 React.memo 或 shouldComponentUpdate,也会在组件本身使用 useContext 时重新渲染。useContext 的参数必须是对象本身

React.memo

1
2
3
const MyComponent = React.memo(function MyComponent(props) {
/* 使用 props 渲染 */
});

介绍:如果你的组件在相同 props 的情况下渲染相同的结果,那么可以通过将其包装在 React.memo 中调用,它通过记忆组件渲染结果的方式来提高组件的性能表现。这意味着在这种情况下,React 将跳过渲染组件的操作并直接复用最近一次渲染的结果。

它仅检查 props 变更。如果函数组件被 React.memo 包裹,且其实现中拥有 useState 或者 useContext 的 Hook,当 context 发生变化时仍会重新渲染。此方法用于性能优化使用,不要依赖它来阻止渲染。

Python 的 count() 方法 是用于统计字符串中某个字符出现的次数。可选参数为在字符串搜索的开始与结束位置。语法:

1
str.count(sub, start= 0,end=len(string))
  1. sub –搜索的子字符串。
  2. start –字符串开始搜索的位置。默认为第一个字符,索引值为0。
  3. end –字符串中结束搜索的位置。字符中的第一个字符的索引为0。默认为字符串的最后一个位置。

返回子字符串在字符串中出现的次数。

暂时总结

今天暂时先探究到这里啦!想不到通过读源码可以学到更多更广的知识,每一行代码都有可学习的地方。