image frame

Storybook从零到一搭建组件库(上篇)

前言

Storybook 是一个绝妙的 组件驱动开发环境。它通过隔离组件使开发更快更容易,它可以一次只处理一个组件。在 web 应用程序中构建小的原子组件和复杂的页面,使用 Storybook 可以让你专注于组件开发,无需去关注 API 文档的编写。

Storybook 可以做什么?

工作中开发的 UI 组件或页面可以用 Storybook 帮助你记录并生成 API 文档,增强代码重用性,大大的提高工作效率,并自动可视化地测试组件以防止 bug。
同时不受限于框架,它同时支持 Vue、React、Angular。所以工作的同时,不妨用它来沉淀一个自己的组件库,面试的时候也是一个谈资。
image

依赖技术栈

首先,先来了解一下搭建一个简单的 UI 组件库需要使用哪些技术栈:

  1. Node 环境:v14.16.1
  2. React@17:用于构建用户界面的 JavaScript 库
  3. TypeScript@^4.5.4:Javascript 类型的超集,有强大的编码提示功能
  4. Ant-design@^4.17.4:最流行的 React 项目 UI 组件库,要搭建的基础组件库是基于 Ant Design 做的二次封装
  5. Create React App:React 脚手架快捷搭建项目架构
  6. Storybook(@storybook/react@^6.4.9):辅助 UI 控件开发的工具,通过 story 创建独立的控件,让每个控件开发都有一个独立的开发调试环境;
  7. Prettier&Eslint&husky:统一规范代码风格交给 Prettier、Eslint 校验语法错误,husky 预防将带有语法等错误提交到远程仓库造成污染
  8. Webpack@^5.0.0:静态模块打包工具

项目准备

阅读更多...

dumi搭建组件库

前言

之前有用 storybook 尝试搭建一套组件库《Storybook 从零到一搭建组件库(上篇)》,但是一顿操作下来之后,发现 storybook 学习成本相对较高且配置复杂,最重要的是页面有被丑到。然后开始使用 dumi,发现真香,不仅上手简单就像正常开发一个普通的项目一样,而且没有繁杂的配置,最重要的是页面美观简洁大方。一个像 antd 一样的组件库,你值得拥有。

本文将带你学习搭建一个 React+TS 组件库,编写一个完整组件、部署至 github 静态 web 站点及发布 npm 。

使用技术:
dumi:负责组件开发及组件文档生成(基于 umi,使用过umi的同学比较友好易上手)
github:配置自动化部署静态 web
gitee:同步 github gh pages

特性:

  • 📦 开箱即用,将注意力集中在组件开发和文档编写上
  • 📋 丰富的 Markdown 扩展,不止于渲染组件 demo
  • 🏷 基于 TypeScript 类型定义,自动生成组件 API
  • 🎨 主题轻松自定义,还可创建自己的 Markdown 组件
  • 📱 支持移动端组件库研发,内置移动端高清渲染方案
  • 📡 一行命令将组件资产数据化,与下游生产力工具串联
阅读更多...

2021,沪漂五年重返校园的一年

img
2021 年,依然是为生活忙碌的一年,考研、考证、换工作……

回想起去年此时正在紧张的备战考研,或许是年龄大了心态不如从前了,考试前夕特别焦虑一度失眠。不过过程都不重要了,因为结果还不错,现在已经入学半学期啦~

工作

我换工作了 💻

就在今年 10 月底我离开了工作两年多的公司,不是裸辞,这个年纪已经没有了裸辞的勇气,原因一言难尽,其实年中就打算走的,但面试了一周左右没有理想的 offer 加之领导的挽留,我放弃了面试,不过 10 月底做完项目后拿到了满意的 offer 还是走了。

回想在那里的两年,平台虽然不大,但是很开心认识了一群可爱的小伙伴和我的的老大(庄哥),他的技术很牛,跟他学到了很多东西,他的技术和为人处事都值得我学习,他是 Coach 型的老大,是我的理想 leader。不过他在我之前离职了,说实话知道他要走的时候我很难过,不知道你们有没有那种很慌又孤军奋战的感觉,感觉工作都提不起兴趣,不过慢慢还是要习惯要自己强大起来。

阅读更多...

Formily入门实践

前言

Formily 是阿里开源的动态化表单的解决方案,优雅的解决了多种复杂场景的表单的数据、状态管理及夸表单通信问题,同时规避了全量渲染的弊端,性能优越。刚好满足我近期工作中的业务需求,啃了将近一周的文档,对 Family 有了初步的了解,后续使用起来再出翻坑指南。

初步了解

​Formily 基于 MVVM 的设计原则,常用的基础核心库有@formily/core@formily/react@formily/vue@formily/antd,支持 react 和 vue,同时支持 Markup Schema、 JSX 以及现在业界最流行的 JSON Schema 的写法。

Formily 分为了内核层UI 桥接层扩展组件层,和配置应用层,如下图。
内核层是 UI 无关的,它保证了用户管理的逻辑和状态是不耦合任何一个框架。
JSON Schema 独立存在,给 UI 桥接层消费,保证了协议驱动在不同 UI 框架下的绝对一致性,不需要重复实现协议解析逻辑。
扩展组件层,提供一系列表单场景化组件,保证用户开箱即用。无需花大量时间做二次开发。
Formily的分层架构图

核心优势

  • 高性能
  • 开箱即用
  • 联动逻辑实现高效
  • 跨端能力,逻辑可跨框架,跨终端复用
  • 动态渲染能力

核心劣势:学习成本较高,需引多个包,包体积较大。

确实 Formily 的学习成本还是相对较高的,几大核心库一堆的文档和 API 会让你眼花缭乱,但是既然要学就要耐下心来,思路理清之后就轻车熟路了。

核心库介绍:
@formily/coreViewModel 层,负责管理表单的状态,表单校验,联动等等。
@formily/react:** Model 层,作为 UI 库来接入内核数据,用来实现最终的表单交互效果,对于不同框架的用户,使用有不同的桥接库,这里使用react为例,使用 vue 安装@formily/vue
@formily/antd
View 层**,在Ant Design基础之上封装的开箱即用的组件库。

使用准备

安装依赖,这里以React+Antd 为例

使用 yarn
yarn add @formily/core
yarn add @formily/react
yarn add antd moment @formily/antd

or 使用 npm
npm install --save @formily/core
npm install --save @formily/react
npm install --save antd moment @formily/antd

导入依赖:

1
2
3
4
import React from 'react'
import { createForm } from '@formily/core'
import { FormProvider, Field } from '@formily/react'
import { FormItem, Input } from '@formily/antd'

实例

JSON Schema写法为例:

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import React from 'react'
import { createForm } from '@formily/core'
import { createSchemaField, FormConsumer, FormProvider } from '@formily/react'
import { FormItem, Input, Password, Submit, FormLayout, FormButtonGroup } from '@formily/antd'
import * as ICONS from '@ant-design/icons'

//用来创建表单核心领域模型,它是作为MVVM设计模式的标准 ViewModel
const form = createForm()

// 创建一个 SchemaField 组件用于解析JSON-Schema动态渲染表单的组件
const SchemaField = createSchemaField({
// 组件列表
components: {
FormLayout,
FormItem,
Input,
Password
},
// 全局作用域,用于实现协议表达式变量注入
scope: {
icon(name: string) {
return React.createElement(ICONS[name])
}
}
})

/**初始化一份json schema
* 解析 json-schema 的能力;将 json-schema 转换成 Field Model 的能力;编译 json-schema 表达式的能力
**/
const schema = {
// schema type
type: 'object',
properties: {
layout: {
type: 'void',
'x-component': 'FormLayout',
'x-component-props': {
labelCol: 2,
wrapperCol: 6,
labelAlign: 'right'
// layout: 'vertical',
},
// 属性描述
properties: {
username: {
// schema type
type: 'string',
// 标题
title: '用户名',
// 必填
required: true,
// 字段 UI 包装器组件
'x-decorator': 'FormItem',
// 字段 UI 组件
'x-component': 'Input',
// 字段 UI 组件属性
'x-component-props': {
prefix: "{{icon('UserOutlined')}}"
}
},
password: {
type: 'string',
title: '密码',
required: true,
'x-decorator': 'FormItem',
'x-decorator-props': {
addonAfter: '强度高'
},
'x-component': 'Password',
'x-component-props': {
prefix: "{{icon('LockOutlined')}}"
}
}
}
}
}
}

export default () => {
return (
<FormProvider form={form}>
<FormLayout layout="vertical">
<SchemaField schema={schema} />
</FormLayout>
<FormButtonGroup>
<Submit onSubmit={console.log}>提交</Submit>
</FormButtonGroup>
<FormConsumer>
{() => (
<div
style={{
width: 340,
marginTop: 20,
padding: 5,
border: '1px dashed #666'
}}
>
实时响应-用户名:{form.values.username}
</div>
)}
</FormConsumer>
</FormProvider>
)
}

image

  • FormProvider组件是作为视图层桥接表单模型的入口,它只有一个参数,就是接收 createForm创建出来的 Form 实例,并将 Form 实例以上下文形式传递到子组件中。
  • FormLayout组件是用来批量控制FormItem样式的组件,这里我们指定布局为水平布局,也就是标签在左,组件在右。
  • FormConsumer组件是作为响应式模型的响应器而存在,它核心是一个render props模式,在作为 children 的回调函数中,会自动收集所有依赖,如果依赖发生变化,则会重新渲染,借助 FormConsumer 我们可以很方便的实现各种计算汇总的需求。
  • FormButtonGroup组件作为表单按钮组容器而存在,主要负责按钮的布局。
  • Submit组件作为表单提交的动作触发器而存在,其实我们也可以直接使用 form.submit 方法进行提交,但是使用 Submit 的好处是不需要每次都在 Button 组件上写 onClick 事件处理器,同时它还处理了 Form loading 状态,如果 onSubmit 方法返回一个 Promise,且 Promise 正在 pending 状态,那么按钮会自动进入 loading 状态。

注意:使用前还需要了解,Formily 已经完全放弃对 IE 的兼容,如需兼容 IE,慎用!!!

参考

Formily 官方文档

webpack之HappyPack

HappyPack makes initial webpack builds faster by transforming files in parallel.
HappyPack 通过并行转换文件,使初始 webpack 构建速度更快。

前言

webpack中万物皆模块,但是webpack默认只能处理js模块,那么js以外的模块怎么处理呢,所以就有了loader机制,比如:vue-loader、css-loader、file-loader等等。loader是一个导出为function的node模块。可以将匹配到的文件进行一次转换,同时loader可以链式传递。如果项目比较复杂,构建时就会有大量文件需要解析和处理,构建是文件读写和计算密集型的操作,大型项目中webpack构建慢的问题尤为显著,然而运行在nodejs环境的webpack是单线程的,如果能让webpack同一时间能做多项任务,发挥多核 CPU 电脑的威力,就能大大的提升构建速度。这时候HappyPack就闪亮登场了,它把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程,相比之前可以有效的提升构建速度。
更多loaders内容参考https://webpack.docschina.org/loaders/

线程和进程都可用于实现并发,一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线。

使用HappyPack

HappyPack提供了一个plugin和一个load完成它的工作,所以你必须同时使用两者来启用它。
使用npm:
npm install --save-dev happypack
使用yarn:
yarn add happypack --dev

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
// @file: webpack.config.js
var HappyPack = require('happypack');
// 构造出共享进程池,进程池中包含5个子进程
var happyThreadPool = HappyPack.ThreadPool({ size: 5 });
<!--more-->
module.exports = {
module: {
rules: [
{
test: /\.js$/,
// 将.js文件交给id为babel的happypack实例来执行
// 1) 用happypack/loader代原始的loaders列表
use: 'happypack/loader?id=babel',
// 排除 node_modules 目录下的文件,node_modules 目录下的文件都是采用的 ES5 语法,没必要再通过 Babel 去转换
exclude: path.resolve(__dirname, 'node_modules'),
}
]
},
plugins: [
// 2)创建一个plugin
new HappyPack({
// id标识happypack处理那一类文件
id: 'babel',
// 共享线程池
threadPool: happyThreadPool,
// 3) 配置一个替代步骤1) 中的loader
loaders: [ 'babel-loader' ],
// 日志输出
verbose: true
})
]
};

在module中定义loader rules告诉 webpack 如何处理特定格式的文件,调用基础配置里的happy/loader,此loader会通过参数的id遍历真实的插件数组,然后找到对应的happyPlugin,通过happyPlugin的配置获取真实的Loader并通过之前初始化完成的多线程进行编译,将编译结果传递给主线程。编译完成后,插件还会针对编译的结果缓存,以及新编译的文件进行缓存的设置。

在实例化 HappyPack 插件的时候,HappyPack 支持如下参数:

  1. loaders:Array

由一个转换文件的loader名和一个查询字符串组成。例如:use: 'happypack/loader?id=babel',用happypack/loader代原始的loaders列表,唯一的happyPack plugin标识,用于在modules rules中去识别对应的happyPack实例中的loaders去执行文件的转换操作。

  1. id: String

happy plugin 的唯一标识。默认值”1”,如果只有一个happy plugin可以不指定,当使用不止一个happy plugin时需要指定它。

  1. threads: Number

代表开启几个子进程去处理这一类型的文件,默认是3个,类型必须是整数。

  1. threadPool: HappyThreadPool

代表共享进程池,即多个 HappyPack 实例都使用同一个共享进程池中的子进程去处理任务,以防止资源占用过多。默认值:null。

  1. verbose: Boolean

是否允许 HappyPack 输出日志,默认是 true。

HappyPack 并不是完全支持所有的webpack loader API,具体支持情况请查看官方wiki

HappyPack原理

img

HappyPack是webpack和主要来源文件(如JS源代码)之间的中间件,其中发生了大量的文件转换处理。每次webpack解析一个模块时,HappyPack都会获取它(模块)及其所有依赖项,并将这些文件分发给多个工作线程”线程”。
这些线程实际上是调用转换器的简单node进程。当加载到编译后的版本时,HappyPack会将最终的chunk提供给加载程序。

不同webpack版本下使用建议

img

问:对webpack2&3有效吗?
答:有,webpack2&3需要搭配使用happyPack@^4.0.1
问:对于webpack4有效吗?
答:webpack4可能不太需要。
大意:webpack4已经融合了多线程机制(HappyPack做的工作),因此happypack的作用不是很明显。如果你使用的版本是<4,那么还是可以继续使用HappyPack。在webpack4中有个thread-loader,配置起来更简单,两种方式都可以试一下看看那种方案对你来说最优。

参考文档

HTML、CSS面试题

1. 盒模型的两种标准?如何相互转化
2. BFC
3. 伪类的伪元素用法与区别
4. div宽度为100vw,设置宽高固定比为10:1,怎么设置
5. Flex:1完整写法,分别代表什么意思
6. flex的实现原理
7. flex垂直居中兼容ie
8. rem的使用原理
9. 移动端300毫秒延迟,怎么解决的
10. 回流和重汇
阅读更多...

JS系列面试题

1. 数据类型有哪些
2. For of 和 for in 的区别
3. Map和 object 的区别有哪些,weakMap了解么,和Map区别是什么
4. 为什么要进行垃圾回收,垃圾回收的原理
5. 0.1+0.2等于0.3么,为什么不等,有什么好的处理办法么,10转成二进制怎么表示
6. 继承有哪些方式,最有效是哪种,如何实现的
7. Var和let的区别有哪些, 浏览器环境下,全局作用域的let和var 声明变量会挂载到 window上么 ,const的值可以修改么,为什么
8. Object.defineProperty的作用是什么,和proxy的区别
9. reduce用法
10. 防抖和节流使用场景
阅读更多...

VUE系列面试题

1. vue双向绑定的原理
2. vue通信方式
3. 组件中的data用箭头函数行不行
4. vue生命周期
5. vue的keep-alive
6. vue与react有什么相同点/不同点
7. vue的 $listeners
8. vue修饰符.sync
9. vue的渲染是异步还是同步,为什么
10. vue的nextTick的用法及场景
阅读更多...

vue-elementui-diary

title
  • Copyrights © 2015-2022 Lillian
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信