01 - Vue3 UI Framework - 开始
写在前面
一年多没写过博客了,工作、生活逐渐磨平了棱角。
写代码容易,写博客难,坚持写高水平的技术博客更难。
技术控决定慢慢拾起这份坚持,用作技术学习的阶段性总结。
返回阅读列表点击 这里
开始
大前端时代,最近在面试前端工程师的过程中,有感而发,技术更新迭代快,学习成本高。浏览了各大博客论坛,千差万别,比较混乱。最终决定参考 Element UI 的设计风格,主题色选择紫色(受到 MaterialDesignInXamlToolkit 的影响),写一套基于 Vue3 的 UI 框架库和对应的官方网站,方便后期在项目中快速使用,也算是对 Vue3 新特性的学习和总结。
先看一下 Jeremy UI 官网 效果吧!目前项目依然处于开发阶段,小伙伴们有兴趣可以跟着一起练习一下,也欢迎参与到项目中,项目参考地址 GitHub ,欢迎 star、issue、fork 和 PR。
分析官网
界面布局
1. 顶部边栏
2. 首页
3. 文档页
3.1 侧边栏
3.2 内容区域
主题风格
紫色
详细说明
位置 | 特性 |
布局 | 两侧留白,内容在中间 最大宽度 1200px,小于 1200px 时,宽度 100% 小于 500px 时,变为手机版 |
顶部边栏 | 左侧是通往首页的跳转链接,右侧是通往文档页的跳转链接 视口小于 500px 时,只显示前往首页的跳转 |
首页 | 分为两部分,视觉效果部分和特点介绍部分 |
首页视觉 | 紫色极光背景,中间放置两个跳转链接,一个前往 github 查看代码,另一个前往文档页 |
首页特点 | 包含 3 个特点,分别是 1. 使用了 vue3 新特性 2. 使用 ts 3. 代码易读 |
文档页 | 文档页实际由顶边栏和本体构成,本体包含侧边栏和内容区域 |
顶边栏-文档页 | 小于 500px 时,在左侧额外显示弹出侧边栏的按键,并使得侧边栏不可见 |
侧边栏 | 默认可见,选中高亮,但视口宽度小于 500px 时,默认不可见 包含两个部分:指南和组件,各自有子级跳转 |
内容区域 | 根据侧边栏中选中的链接,显示 md 内容或组件范例内容 |
搭建官网
创建方式有很多,而我这里选择通过 Vite 进行创建 Vue3 项目,为什么选 Vite 呢?如下是 Vite 官网 的说法:
现实问题
在浏览器支持 ES 模块之前,JavaScript 并没有提供原生机制让开发者以模块化的方式进行开发。这也正是我们对 “打包” 这个概念熟悉的原因:使用工具抓取、处理并将我们的源码模块串联成可以在浏览器中运行的文件。
时过境迁,我们见证了诸如 webpack、Rollup 和 Parcel 等工具的变迁,它们极大地改善了前端开发者的开发体验。
然而,当我们开始构建越来越大型的应用时,需要处理的 JavaScript 代码量也呈指数级增长。包含数千个模块的大型项目相当普遍。我们开始遇到性能瓶颈 —— 使用 JavaScript 开发的工具通常需要很长时间(甚至是几分钟!)才能启动开发服务器,即使使用 HMR,文件修改后的效果也需要几秒钟才能在浏览器中反映出来。如此循环往复,迟钝的反馈会极大地影响开发者的开发效率和幸福感。
Vite 旨在利用生态系统中的新进展解决上述问题:浏览器开始原生支持 ES 模块,且越来越多 JavaScript 工具使用编译型语言编写。
缓慢的服务器启动
当冷启动开发服务器时,基于打包器的方式启动必须优先抓取并构建你的整个应用,然后才能提供服务。
Vite 通过在一开始将应用中的模块区分为 依赖 和 源码 两类,改进了开发服务器启动时间。
依赖 大多为在开发时不会变动的纯 JavaScript。一些较大的依赖(例如有上百个模块的组件库)处理的代价也很高。依赖也通常会存在多种模块化格式(例如 ESM 或者 CommonJS)。
Vite 将会使用 esbuild 预构建依赖。Esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。
源码 通常包含一些并非直接是 JavaScript 的文件,需要转换(例如 JSX,CSS 或者 Vue/Svelte 组件),时常会被编辑。同时,并不是所有的源码都需要同时被加载(例如基于路由拆分的代码模块)。
Vite 以 原生 ESM 方式提供源码。这实际上是让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。
缓慢的更新
基于打包器启动时,重建整个包的效率很低。原因显而易见:因为这样更新速度会随着应用体积增长而直线下降。
一些打包器的开发服务器将构建内容存入内存,这样它们只需要在文件更改时使模块图的一部分失活[1],但它也仍需要整个重新构建并重载页面。这样代价很高,并且重新加载页面会消除应用的当前状态,所以打包器支持了动态模块热重载(HMR):允许一个模块 “热替换” 它自己,而不会影响页面其余部分。这大大改进了开发体验 —— 然而,在实践中我们发现,即使采用了 HMR 模式,其热更新速度也会随着应用规模的增长而显著下降。
在 Vite 中,HMR 是在原生 ESM 上执行的。当编辑一个文件时,Vite 只需要精确地使已编辑的模块与其最近的 HMR 边界之间的链失活[1](大多数时候只是模块本身),使得无论应用大小如何,HMR 始终能保持快速更新。
Vite 同时利用 HTTP 头来加速整个页面的重新加载(再次让浏览器为我们做更多事情):源码模块的请求会根据
304 Not Modified
进行协商缓存,而依赖模块请求则会通过Cache-Control: max-age=31536000,immutable
进行强缓存,因此一旦被缓存它们将不需要再次请求。一旦你体验到 Vite 的神速,你是否愿意再忍受像曾经那样使用打包器开发就要打上一个大大的问号了。
为什么生产环境仍需打包
尽管原生 ESM 现在得到了广泛支持,但由于嵌套导入会导致额外的网络往返,在生产环境中发布未打包的 ESM 仍然效率低下(即使使用 HTTP/2)。为了在生产环境中获得最佳的加载性能,最好还是将代码进行 tree-shaking、懒加载和 chunk 分割(以获得更好的缓存)。
要确保开发服务器和生产环境构建之间的最优输出和行为一致并不容易。所以 Vite 附带了一套 构建优化 的 构建命令,开箱即用。
为何不用 ESBuild 打包?
虽然
esbuild
快得惊人,并且已经是一个在构建库方面比较出色的工具,但一些针对构建 应用 的重要功能仍然还在持续开发中 —— 特别是代码分割和 CSS 处理方面。就目前来说,Rollup 在应用打包方面更加成熟和灵活。尽管如此,当未来这些功能稳定后,我们也不排除使用esbuild
作为生产构建器的可能。
在开始之前我们需要注意兼容性问题:
兼容性注意
Vite 需要 Node.js 版本 >= 12.0.0
使用 npm 创建 jeremy-ui 项目
直接创建
1 mkdir jeremy-ui
2 cd jeremy-ui
3 cva .
脚手架创建(根据提示信息创建即可,注意选择 vue -> vue-ts)
启动项目
1 cd jeremy-ui
2 npm install
3 npm run dev
正常情况下,你就可以在浏览器上( http://localhost:3000/ ) 预览项目了。
注意:
如果你不是通过脚手架去创建的项目,那么你可能需要将 main.js 改成 main.ts 。另外,你还需要在 src 目录下添加 shims.d.ts 文件,让 ts 文件能够识别 vue 后缀的文件。
shims.d.ts 文件源码如下:
1 declare module '*.vue' {
2 import { ComponentOptions } from 'vue'
3 const componentOptions: ComponentOptions
4 export default componentOptions
5 }
整体布局设计
根据之前的分析,我们能够得出结论,首先,最大宽度限制需要作用到 app 上,所以相应的样式应该写在 app.vue 上,其次,首页和文档页的顶边栏,其功能为:
位置 | 功能 |
首页 | 禁止弹出菜单 |
文档页 | 根据情况显示或者隐藏菜单 |
可见并不完全相同,也就是说不是同一个组件的复用,所以应该将顶边栏组件分别嵌入首页和文档页组件,而不是嵌入 app.vue ,
然后,首页显然没有侧边栏,所以首页的内容直接写在其模板内即可,而文档页需要侧边栏和内容区域,但是文档页的侧边栏,实际上与弹出的顶部菜单是相同的内容,所以只需要编写一次,然后复用为侧边栏和顶部菜单即可。
除此之外,文档页的内容区域,还要分别展示 markdown 内容和组件内容,所以内容区域要分成两种进行编写。
综上,首页大致为上下结构,恒定不变;文档页大致为 T 字结构,小于 1200px 时为上下结构,附有弹出菜单的选项。
总体样式表 index.scss (可能需要修改 index.css 的后缀)
1 * {
2 margin: 0;
3 padding: 0;
4 box-sizing: border-box;
5 }
6 ul,
7 ol {
8 list-style: none;
9 }
10 a {
11 text-decoration: none;
12 color: inherit;
13 &:hover {
14 text-decoration: underline;
15 cursor: pointer;
16 }
17 }
18 h1,
19 h2,
20 h3,
21 h4,
22 h5,
23 h6 {
24 font-weight: normal;
25 }
26
27 body {
28 font-size: 16px;
29 line-height: 1.5;
30 color: #1d2c40;
31 font-family: -apple-system, "Noto Sans", "Helvetica Neue", Helvetica,
32 "Nimbus Sans L", Arial, "Liberation Sans", "PingFang SC", "Hiragino Sans GB",
33 "Noto Sans CJK SC", "Source Han Sans SC", "Source Han Sans CN",
34 "Microsoft YaHei", "Wenquanyi Micro Hei", "WenQuanYi Zen Hei", "ST Heiti",
35 SimHei, "WenQuanYi Zen Hei Sharp", sans-serif;
36 }
37 .icon {
38 width: 1em; height: 1em;
39 vertical-align: -0.15em;
40 fill: currentColor;
41 overflow: hidden;
42 }
然后修改 main.ts 中的引入
1 import './index.scss'
最后完成 App.vue 的内容
1 <template>
2 <div class="app">
3 <router-view />
4 </div>
5 </template>
6
7 <script lang="ts">
8 export default {
9 name: "App",
10 };
11 </script>
12 <style lang="scss" scoped>
13 $max-width: 1200px;
14 .app {
15 max-width: $max-width;
16 margin-left: calc(50vw - 600px);
17 position: relative;
18 @media (max-width: $max-width) {
19 margin-left: 0;
20 }
21 }
22 </style>
依赖包的安装
请参考 package.json 文件,对应更新一下,然后再项目根目录下执行 npm install 即可。
1 {
2 "name": "jeremy-ui",
3 "version": "0.0.3",
4 "files": [
5 "lib/*"
6 ],
7 "main": "lib/jeremy.js",
8 "scripts": {
9 "dev": "vite",
10 "build": "vite build"
11 },
12 "dependencies": {
13 "github-markdown-css": "^4.0.0",
14 "marked": "^1.2.8",
15 "prismjs": "^1.23.0",
16 "vue": "^3.0.4",
17 "vue-router": "^4.0.4"
18 },
19 "devDependencies": {
20 "@vue/compiler-sfc": "^3.0.4",
21 "rollup-plugin-esbuild": "^4.7.2",
22 "rollup-plugin-scss": "^3.0.0",
23 "rollup-plugin-terser": "^7.0.2",
24 "rollup-plugin-vue": "^6.0.0",
25 "sass": "^1.44.0",
26 "vite": "^1.0.0-rc.13"
27 }
28 }
路由设计
既然有多个页面,那肯定就要通过路由进行跳转。路由显然是使用 vue-router
,首先安装它。要注意,默认安装的 vue-router
是 3.x.x
版本的,只能用于 vue2,要想用于 vue3,必须是 4.x.x
版本
通过 npm info vue-router 可以看到最新版(next 版本)是 4.0.4
(如有变化,下载最新版即可),则我们通过 npm install vue-router@4.0.4 安装适合 vue3 的 vue-router。
Jeremy UI 官网的路由设计如下:
目标 | 路由 |
首页 | / |
文档页 | /document |
文档页 - 介绍 | /document/introduction |
文档页 - 安装 | /document/install |
文档页 - 快速上手 | /document/start |
文档页 - [组件名] | /document/[componentName] |
因为目前还没有试图,所以我们先把框架写好,暂时写一个空的引入即可,router.ts 如下
1 import { createWebHistory, createRouter } from 'vue-router'
2
3 const history = createWebHistory()
4 const router = createRouter({
5 history,
6 routes: [
7 ]
8 })
9 export default router
然后再在 main.ts 中引入
1 import { createApp } from 'vue'
2 import App from './App.vue'
3 import './index.scss'
4 import router from './router'
5
6 createApp(App).use(router).mount('#app')
使用 SVG
为了官网的相对美观,我们决定使用 SVG,可以使用 icon font 提供的免费图标,使用教程大致如下
- 选择喜欢的图标,加入购物车
- 新建一个项目,或选择一个已有项目,将购物车里的图标加入该项目
- 进入”我的项目”,生成新的引用链接
- 选择
Symbol
模式,复制链接,粘贴到本地项目的index.html
的新 script 标签中
之后就可以在本地使用如下的方式引用 svg 了
1 <svg>
2 <use xlink:href="#icon-Vue"></use>
3 </svg>
svg 的命名,参考 icon font 上”我的项目”里设置的每个图标的名称,另外,如果项目中的图标有任何变化,必须要重新生成引用链接!
相关资源
GitHub 仓库:jeremy-ui
Jeremy UI 官网地址:Jeremy UI
GitHub 分支说明
分支名称 | 说明 |
main | 合并的 dev 分支的 PR |
dev | 开发分支,组件库的引用来自本地 |
publish | GitHub Pages 发布的分支 |
website | 官网使用的分支,组件库的引用来自 npm |
小伙伴 clone 之后可以参考 main 分支,可以向 dev 分支提交 PR 哦!
参考资料
知乎 - 随安
掘金 - 大威Wayne
Vite 官方 - Vite
阿里矢量图标库 - Iconfont
01 - Vue3 UI Framework - 开始的更多相关文章
- 00 - Vue3 UI Framework - 阅读辅助列表
阅读列表 01 - Vue3 UI Framework - 开始 02 - Vue3 UI Framework - 顶部边栏 03 - Vue3 UI Framework - 首页 04 - Vue3 ...
- 05 - Vue3 UI Framework - Button 组件
官网基本做好了,接下来开始做核心组件 返回阅读列表点击 这里 目录准备 在项目 src 目录下创建 lib 文件夹,用来存放所有的核心组件吧.然后再在 lib 文件夹下创建 Button.vue 文件 ...
- 03 - Vue3 UI Framework - 首页
顶部边栏做完了,接下来开始做官网的首页 返回阅读列表点击 这里 创建视图文件夹 让我们先新建一个 src/views 文件夹,用来存放官网的主要视图 然后在该文件夹下新建两个 vue 文件,作为我们的 ...
- 06 - Vue3 UI Framework - Dialog 组件
做完按钮之后,我们应该了解了遮罩层的概念,接下来我们来做 Dialog 组件! 返回阅读列表点击 这里 需求分析 默认是不可见的,在用户触发某个动作后变为可见 自带白板卡片,分为上中下三个区域,分别放 ...
- 08 - Vue3 UI Framework - Input 组件
接下来再做一个常用的组件 - input 组件 返回阅读列表点击 这里 需求分析 开始之前我们先做一个简单的需求分析 input 组件有两种类型,即 input 和 textarea 类型 当类型为 ...
- 09 - Vue3 UI Framework - Table 组件
接下来做个自定义的表格组件,即 table 组件 返回阅读列表点击 这里 需求分析 开始之前我们先做一个简单的需求分析 基于原生 table 标签的强语义 允许用户自定义表头.表体 可选是否具有边框 ...
- 10 - Vue3 UI Framework - Tabs 组件
标签页是非常常用的组件,接下来我们来制作一个简单的 Tabs 组件 返回阅读列表点击 这里 需求分析 我们先做一个简单的需求分析 可以选择标签页排列的方向 选中的标签页应当有下划线高亮显示 切换选中时 ...
- 11 - Vue3 UI Framework - Card 组件
卡片是非常常用也是非常重要的组件,特别是在移动端的众多应用场景中,随便打开一个手机 App ,您会发现充斥着各种各样的卡片. 所以,我们也来制作一个简易的 Card 组件 返回阅读列表点击 这里 需求 ...
- 12 - Vue3 UI Framework - 打包发布
基础组件库先做到这个阶段,后面我会继续新增.完善 接下来,我们对之前做的组件进行打包发布到 npm 返回阅读列表点击 这里 组件库优化 通用层叠样式表 我想大家都注意到了,前面我们在写组件的时候,sc ...
随机推荐
- [atAGC048E]Strange Relation
考虑对于$\{a_{i+1},...,a_{n}\}$,在其前面插入$a_{i}$对$x_{i}$的影响(不考虑$a_{1}$到$a_{i-1}$): 1.$x_{i}=0$,因为其前面没有数字了 2 ...
- [bzoj1005]明明的烦恼
根据purfer序列的原理,每一个purfer序列都一一对应了一棵树,每一个点在purfer序列中出现的次数就是它的度数,那么直接用组合数去计算即可,注意要加高精度 1 #include<cst ...
- es插件安装
首先安装找到一样版本的地址: Release v7.6.1 · medcl/elasticsearch-analysis-ik (github.com) 下载最上面的编译版 将文件解压到plugins ...
- 新玩法-使用AllArgsConstructor+filal代替autowired
和下面的代码一样: Springboot官方建议使用final来修饰成员变量,然后通过构造方法来进行注入原因:final修饰的成员变量是不能够被修改的,反射那就没办法了 还有一种写法: @Requir ...
- 9.1 k8s pod版本更新流程及命令行实现升级与回滚
1.创建 Deployment root@k8-deploy:~/k8s-yaml/controllers/deployments# vim nginx-deployment.yaml apiVers ...
- IntelliJ IDEA 2021.3 正式发布:支持远程开发、IDE故障排查等多项优化改进
作者:程序猿DD 博客:https://blog.didispace.com/ 昨天刚刚跟大家聊了Jetbrains即将推出轻量级编辑器Fleet,以挑战 VS Code的消息,今天又收到了Intel ...
- Codeforces 1368H - Breadboard Capacity(最小割+线段树维护矩阵乘法)
Easy version:Codeforces 题面传送门 & 洛谷题面传送门 Hard version:Codeforces 题面传送门 & 洛谷题面传送门 首先看到这种从某一种颜色 ...
- Codeforces 704C - Black Widow(dp)
Codeforces 题目传送门 & 洛谷题目传送门 u1s1 感觉这种题被评到 *2900 是因为细节太繁琐了,而不是题目本身的难度,所以我切掉这种题根本不能说明什么-- 首先题目中有一个非 ...
- 洛谷 P3270 - [JLOI2016]成绩比较(容斥原理+组合数学+拉格朗日插值)
题面传送门 考虑容斥.我们记 \(a_i\) 为钦定 \(i\) 个人被 B 神碾压的方案数,如果我们已经求出了 \(a_i\) 那么一遍二项式反演即可求出答案,即 \(ans=\sum\limits ...
- CF1466G Song of the Sirens
题目传送门 题意简述:给出 \(n,s_0,t\ (n=|t|)\),定义 \(s_i=s_{i-1}+t_i+s_{i-1}\).多次询问给出 \(k,m\),求 \(m\) 在 \(s_k\) 中 ...