本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!
- 前言
大家好,我是若川。我倾力持续组织了一年每周大家一起学习200行左右的源码共读活动,感兴趣的可以点此扫码加我微信 ruochuan02
参与。另外,想学源码,极力推荐关注我写的专栏《学习源码整体架构系列》,目前是掘金关注人数(4.1k+人)第一的专栏,写有20余篇源码文章。
我们开发业务时经常会使用到组件库,一般来说,很多时候我们不需要关心内部实现。但是如果希望学习和深究里面的原理,这时我们可以分析自己使用的组件库实现。有哪些优雅实现、最佳实践、前沿技术等都可以值得我们借鉴。
相比于原生 JS
等源码。我们或许更应该学习,正在使用的组件库的源码,因为有助于帮助我们写业务和写自己的组件。
如果是 Vue
技术栈,开发移动端的项目,大多会选用 vant
组件库,目前(2022-10-31) star
多达 20.4k
。我们可以挑选 vant
组件库学习,我会写一个vant 组件库源码系列专栏,欢迎大家关注。
vant 组件库源码分析系列:
- 1.vant 4 即将正式发布,支持暗黑主题,那么是如何实现的呢
- 2.跟着 vant 4 源码学习如何用 vue3+ts 开发一个 loading 组件,仅88行代码
- 3.分析 vant 4 源码,如何用 vue3 + ts 开发一个瀑布流滚动加载的列表组件?
- 4.分析 vant 4 源码,学会用 vue3 + ts 开发毫秒级渲染的倒计时组件,真是妙啊
- 5.vant 4.0 正式发布了,分析其源码学会用 vue3 写一个图片懒加载组件!
这次我们来学习 loading 组件。
学完本文,你将学到:
1 | bash复制代码1. 学会如何用 vue3 + ts 开发一个 loading 组件 |
- 准备工作
看一个开源项目,第一步应该是先看 README.md 再看贡献文档 github/CONTRIBUTING.md。
2.1 克隆源码 && 跑起来
You will need Node.js >= 14 and pnpm.
1 | bash复制代码# 推荐克隆我的项目 |
我们先来看 pnpm dev
最终执行的什么命令。
vant
项目使用的是 monorepo
结构。查看根路径下的 package.json
。
vant/package.json => "dev": "pnpm --dir ./packages/vant dev"
vant/packages/vant/package.json
=> “dev”: “vant-cli dev”`
pnpm dev
最终执行的是:vant-cli dev
启动了一个服务。本文主要是学习 loading 组件 的实现,所以我们就不深入 vant-cli dev
命令了。
- 从官方文档入手找到 demo 文件
有些小伙伴喜欢在新的项目中去安装组件,再去自行新建 demo
文件去调试预览。一般来说,其实没有必要。开源项目中一般就有 demo
类文件了。直接学习即可,省去新建的麻烦。
我们凭着前端人直觉,应该很容易在找到 loading
文件夹的路径:vant/packages/vant/src/loading/demo/index.vue
。
但真的是这个路径吗?或者说这个路径是怎么渲染到官方文档中页面上的呢。带着这个疑问,我们从文档网站入手。
我们很容易我们通过 http://localhost:5173/#/zh-CN/loading
。
接下来我们来看,这个页面的对应的文件是在哪里,为啥路由 loading
就能到达这个页面。
3.1 mobile 项目中的 DemoBlock 组件
我们通过 vue-devtools 可以找到和打开 DemoBlock
组件文件。也可以通过极简插件下载安装。我曾经写过文章分析原理《据说 99% 的人不知道 vue-devtools 还能直接打开对应组件文件?本文原理揭秘》
打开后的文件是这样的,主要传入插槽,还有 card
和 title
属性。
1 | js复制代码// vant/packages/vant-cli/site/mobile/components/DemoBlock.vue |
在编辑器左侧,我们可以看到 vant-cli/site
目录结构。
3.2 mobile 项目中的 main.js 主入口文件
我们很容易看出这就是一个 vue
的项目。我们打开 main.js
查看。
1 | js复制代码// vant/packages/vant-cli/site/mobile/main.js |
3.3 mobile 项目中的 App.vue 文件
1 | js复制代码// 省略其他文件 |
查看vue-router 文档,可以发现:<router-view>
暴露了一个 v-slot
API,主要使用 <transition>
和 <keep-alive>
组件来包裹你的路由组件。Component
: VNodes, 传递给 <component>
的 is
prop。route
: 解析出的标准化路由地址。
3.4 mobile 项目中的 rotuer.js 路由文件
1 | js复制代码// vant/packages/vant-cli/site/mobile/router.js |
按调试点进函数看到截图,可以看到具体代码和路径。
1 | js复制代码// http://localhost:5173/@id/vant-cli:site-mobile-shared?t=1667051150300 |
果然,确实是我们在前文猜测路径 vant/packages/vant/src/loading/demo/index.vue
。
小结:通过路由 /loading
匹配组件 demos
中的组件 Loading
component: () => import('xxx/loading/demo/index.vue')
,<router-view>
传递给 v-slot
Component
<component :is="Component" />
属性渲染,不得不说妙啊。
接着我们继续来看,loading
的 demo
文件。
- loading demo 文件 loading/demo/index.vue
1 | js复制代码// vant/packages/vant/src/loading/demo/index.vue |
vue 文档 component is如果将组件本身传递给 is
而不是其名称,则不需要注册,例如在 <script setup>
中。
也就是为什么不需要注册 VanLoading
。
而 demo-block
是在 mobile
main.js
入口文件注册的。
1 | js复制代码window.app = createApp(App) |
- loading 入口文件 loading/index.ts
组件源码中的 TS
代码我不会过多解释。没学过TS的小伙伴,推荐学这个TypeScript 入门教程。
1 | js复制代码// vant/packages/vant/src/loading/index.ts |
5.1 withInstall 给组件对象添加 install 方法
1 | js复制代码import { camelize } from './format'; |
关于 app.component
的用法,更多可以参考 vue 文档 app-component
我们来讲讲安装。
5.2 安装 vant
1 | bash复制代码# Vue 3 项目,安装最新版 Vant |
1 | bash复制代码npm dist-tag vant |
对应的则是:npmjs.com 上 vant 介绍 的版本。
为啥讲这么详细,因为之前源码共读群里有小伙伴问这些版本安装的问题。
我猜测很多人虽然经常使用 npm
,但很少有完整看过 npm
文档的。docs npmjsnpm
也是脚手架,如果想看 npm i
, npm dist-tag
等源码实现,可以查看它的github 源码仓库。
1 | jsx复制代码import { createApp } from 'vue'; |
1 | html复制代码<van-loading /> |
关于 app.use
的用法更多可以参考vue 文档 app.use
我们继续看主文件。
- 主文件 loading/Loading.tsx
主结构最后就是渲染图标和渲染文字。你可能会感慨原来就是这么简单。
1 | js复制代码// vant/packages/vant/src/loading/Loading.tsx |
有小伙伴可能注意到了,这感觉就是和 react
类似啊。其实 vue
也是支持 jsx
。不过需要配置插件 @vue/babel-plugin-jsx
。全局搜索这个插件,可以搜索到在 vant-cli
中配置了这个插件。
我们再来看前面完整的,介绍一些工具函数等。
1 | js复制代码// vant/packages/vant/src/loading/Loading.tsx |
我们来看从 utils
文件引入的函数。
6.1 工具函数 extend
1 | js复制代码export const extend = Object.assign; |
就是取了个 Object.assign
别名。值得提醒的一点是:
Object.assign
是浅复制。参数也可以是 undefined
,不会报错。
1 | js复制代码const props = { |
6.2 工具函数 addUnit 添加单位
1 | ts复制代码// vant/packages/vant/src/utils/format.ts |
6.3 工具函数 numericProp 数字或字符串属性
1 | js复制代码export const numericProp = [Number, String]; |
6.4 工具函数 getSizeStyle 获取样式
1 | js复制代码export type Numeric = number | string; |
1 | js复制代码import type { CSSProperties } from 'vue'; |
6.5 工具函数 createNamespace 创建域名空间
1 | js复制代码// vant/packages/vant/src/utils/create.ts |
分析完工具函数,我们就基本分析完了 loading
组件,代码函数不多,主文件就 88 行。
- 总结
我们从分析找到 demo
文件的位置 loading/demo/index.vue
,找到入口文件 loading/index.ts
,简要描述了安装 vant
对应 npm
版本和 loading
主文件 loading/Loading.tsx
工具函数。
其中 demo
文件位置原理设计的很巧妙。通过路由 /loading
匹配组件 demos
中的组件 Loading
component: () => import('xxx/loading/demo/index.vue')
,<router-view>
传递给 v-slot
Component
<component :is="Component" />
属性渲染。
源码也不是我们想象中的那么难,耐心学下来一定会有很多收获。
相比于原生 JS
等源码。我们或许更应该学习,正在使用的组件库的源码,因为有助于帮助我们写业务和写自己的组件。开源项目通常有很多优雅实现、最佳实践、前沿技术等都可以值得我们借鉴。
如果是自己写开源项目相对耗时耗力,而且短时间很难有很大收益,很容易放弃。而刚开始可能也无法参与到开源项目中,这时我们可以先从看懂开源项目的源码做起。对于写源码来说,看懂源码相对容易。看懂源码后可以写文章分享回馈给社区,也算是对开源做出一种贡献。重要的是行动起来,学着学着就会发现很多都已经学会,锻炼了自己看源码的能力。
如果看完有收获,欢迎点赞、评论、分享支持。你的支持和肯定,是我写作的动力。
最后可以持续关注我@若川。这是 vant
第二篇文章。
上一篇是:vant 4 即将正式发布,支持暗黑主题,那么是如何实现的呢。我会写一个组件库源码系列专栏,欢迎大家关注。
我倾力持续组织了一年每周大家一起学习200行左右的源码共读活动,感兴趣的可以点此扫码加我微信 ruochuan02
参与。
另外,想学源码,极力推荐关注我写的专栏《学习源码整体架构系列》,目前是掘金关注人数(4.1k+人)第一的专栏,写有20余篇源码文章。包含jQuery
、underscore
、lodash
、vuex
、sentry
、axios
、redux
、koa
、vue-devtools
、vuex4
、koa-compose
、vue 3.2 发布
、vue-this
、create-vue
、玩具vite
、create-vite
等20余篇源码文章。
本文转载自: 掘金