关于组件库:使用-NutUI-搭建自定义业务风格的组件库-京东云技术团队

作者:京东批发 佟恩 本文介绍,如何应用 NutUI 组件库,搭建一套为专属业务格调的业务组件库。 NutUI 是一款京东格调的挪动端组件库。NutUI 目前反对 Vue 和 React技术栈,反对Taro多端适配。当下的实现形式个别组件库,都会给用户提供批改主题的形式。比方在 NutUI 组件库中,给用户提供了两种形式: 批改CSS变量,NutUI 组件库反对通过全局配置组件 ConfigProvider 组件实现主题定制;const customTheme = { nutuiBadgeBorderRadius: '12px 12px 12px 0',}<ConfigProvider theme={customTheme}> <Badge value="NEW"> <Avatar icon="my" shape="square" /> </Badge></ConfigProvider>通过SCSS 变量,NutUI 组件库提供通过编写一套自定义主题的款式文件,间接笼罩现有款式文件,实现主题定制。// 新建一个 SCSS 文件 custom_theme.scss 进行自定义// 主色调$primary-color: #478EF2;$primary-color-end: #496AF2;// vue 版本{ test: /\.(sa|sc)ss$/, use: [ { loader: 'sass-loader', options: { // 留神:在 sass-loader 不同版本,这个选项名是 是不一样的,具体可参考 sass-loader对应的版本文档 data: `@import "@/assets/custom_theme.scss";@import "@nutui/nutui-react/dist/styles/variables.scss";`, } } ]}以后问题与解决思路以上两种形式,对于咱们实现单个我的项目来讲,还是比较简单的,然而如果咱们业务条线下的每一个我的项目都须要这样接入,那这个接入形式就会显得蠢笨起来。 那咱们怎么能力优雅的接入呢? 咱们的思路是,NutUI 与业务侧一起,独特输入一套属于本人业务格调的组件库。 其中,NutUI 提供组件库反对主题定制的配置和编译能力,业务侧输入交互与视觉标准,共同完成组件库的适配计划,输入定制化组件库的 NPM 包,进而在业务我的项目中提供反对。 ...

May 6, 2023 · 1 min · jiezi

关于组件库:Storybook使用过程遇到的一些问题

老早就晓得 Storybook 这个用于开发组件库生成文档的工具,但始终未在生产环境实际过,上面讲一下我最近遇到的一个问题根本介绍、装置过程暂且不谈,可去官网理解Storybook 根底介绍中文文档、最新文档 问题:docs 文档不显示因为我是接手的他人的我的项目,这个我的项目的 storybook 均已初始化结束,但有一个问题是 docs 菜单不显示内容,这就带来了一个问题:就是我在 storybook 找到了我须要的组件然而我却无奈间接复制只能去源码找到相应代码而后拷贝下来其过程非常苦楚繁琐 解决问题的步骤 一度认为是控制台的那个报错影响的不展现,就玩命的搜寻这个报错的起因,但怎么都找不到答案,而后看到storybook有个docs的插件-@storybook/addon-docs,装置应用也是杯水车薪,docs 菜单怎么也搞不进去而后想到初始化一个最简略的 storybook 我的项目看一看它与现有我的项目中的配置哪里不统一,而后利用 npx sb init 文档初始了一个我的项目,这里多说一句,官网文档指明 sb init 不针对一个空我的项目,而是一个曾经应用框架的我的项目而后启动发现 docs 菜单是能失常显示的,配置文件 main.js 也没有装置 @storybook/addon-docs 该插件而后我就把现有我的项目的 storybook 的配置文件 (.storybook 目录) 删掉,所有依赖 package.json 的货色全删掉,而后在根目录执行 npx sb init执行 yarn storybook 而后奇观产生了,docs 目录呈现了 ,合乎预期,但因为我的项目中应用 tailwindcss,storybook 中的组件的款式全都失落了又去搜寻 storybook + react + tailwindcss 如何组合应用,找到了这篇文章 解决了我的问题,docs 菜单菜单呈现了 残缺的配置如下 // .storybook/main.js const path = require('path')module.exports = { stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], addons: [ '@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions', '@storybook/addon-storysource', // 用于底部菜单栏呈现 story 选项 '@storybook/preset-create-react-app', ], // tailwindcss 与 storybook 配合应用 webpackFinal: async config => { config.module.rules.push({ test: /\.css&/, use: [ { loader: 'postcss-loader', options: { ident: 'postcss', plugins: [require('tailwindcss'), require('autoprefixer')], }, }, ], include: path.resolve(__dirname, '../'), }) return config }, framework: '@storybook/react', core: { builder: 'webpack5', },}参考文章storybook中文文档基于 Storybook 5 打造 Style 组件库开发与文档站建设小结Storybook 入门指南

March 18, 2022 · 1 min · jiezi

关于组件库:如何从头到尾做一个UI组件库

首先咱们咱们的这个ui组件库是开发的vue版本,如果须要变通其余版本的话,就把vue相干的编译器移除,其余相干的编译器加上就能够了(例如react),打包构建形式是通用的。组件库的组织发版和我的项目是不太一样的,这里提下思路。首先咱们要确定咱们做的库要满足的需要: 反对全副加载反对按需加载ts的补充类型反对同时反对cjs和esm版本晓得了咱们要反对的需要之后,要确定一下咱们最初包的目录构造是什么样的,如下:这简略形容下为何是这样的构造,首先index.esm是 咱们整全量的包,外面蕴含了所有的ui组件,还有一个index.cjs版本,在打包工具不反对esm时会应用cjs版本,两个版本能够更好的反对不同的打包工具。 lib下放的是咱们单个组件,用来联合 babel-plugin-import 来做按需加载。这里先简略做一个概括,后续实现的时候会做具体的解释。 好了,理解了 咱们最初的我的项目构造,就要开始ui库的搭建了,后续所有的操作配置,都是为了在保障程序健壮性通用性的根底上来打进去咱们最初要公布的这个包的构造。 设计及流程代码的组织形式MonorepoMonorepo 是治理我的项目代码的一个形式,指在一个我的项目仓库(repo) 中治理多个模块/包(package),不同于常见的每个模块建一个repo。例如: ├── packages| ├── pkg1| | ├── package.json| ├── pkg2| | ├── package.json├── package.json这样的构造,能够看到这些我的项目的第一级目录的内容以脚手架为主,次要内容都在 packages 目录中、分多个package进行治理。 一些出名的库例如vue3.0和react都是采纳这种形式来治理我的项目的。后续咱们会依据这些packages里的小包,来生成按需加载的文件。 包的管理工具采纳yarn,因为咱们要用到它的workspaces依赖治理如果不必workspaces时,因为各个package实践上都是独立的,所以每个package都保护着本人的dependencies,而很大的可能性,package之间有不少雷同的依赖,而这就可能使install时呈现反复装置,使原本就很大的 node_modules 持续收缩(这就是「依赖爆炸」...)。 为了解决这个问题在这里咱们要应用yarn的workspaces个性,这也就是依赖治理咱们为什么应用yarn的起因。而应用yarn作为包管理器的同学,能够在 package.json 中以 workspaces 字段申明packages,yarn就会以monorepo的形式治理packages。应用形式详情能够查看它的官网文档 文档 咱们在package.json开启了yarn 的workspaces工作区之后,以后这个目录被称为了工作区根目录,工作区并不是要公布的,而后这会咱们在下载依赖的时候,不同组件包里的雷同版本的依赖会下载到工作区的node_modules里,如果以后包依赖的版本和其余不一样就会下载到以后包的node_modules里。 yarn的话突出的是对依赖的治理,包含packages 的相互依赖、packages 对第三方的依赖,yarn 会以semver 约定来剖析dependencies 的版本,装置依赖时更快、占用体积更小。 lerna这里简略提一下lerna,因为目前支流的monorepo解决方案是Lerna 和 yarn 的 workspaces 个性,它次要用来管理工作流,然而它个人感觉如果你须要一次性公布packages里的所有包时,用它会比拟不便,咱们这里没有过多的用到它。 Storybook开发阶段的调试组件成果的调试和应用介绍咱们通过Storybook来进行治理,这是一个可视化的组件展现平台,它能够让咱们在隔离的开发环境 交互地开发和测试组件,最初也能够生成应用阐明的动态界面,它反对很多框架例如:vue.react,ng,React Native等。 jest单元测试单元测试的话咱们应用Facebook的jest plop创立雷同模版咱们包的构造是这样的,例如avatar: ├── packages| ├── avatar| | ├── __test__ //单元测试文件| | ├── src //组件文件| | ├── stories //storyBook 开发阶段预览的展现,扫描文件| | ├── index.ts //包入口| | ├── LICENSE| | ├── README.MD| | ├── package.json├── package.json每个UI组件的构造根本都是一样的,所以在这里咱们选用plop来对立生成模版,plop次要用于创立我的项目中特定文件类型的小工具,相似于Yeoman中的sub generator,个别不会独立应用。个别会把Plop集成到我的项目中,用来自动化的创立同类型的我的项目文件。 ...

October 7, 2021 · 10 min · jiezi

关于组件库:业务组件库开发流程

业务组件库必要性我的项目通过长期保护之后往往会积淀出很多公共组件,当一个组件编写实现之后,其余维护者想要应用这个组件,理解这个组件是做什么的,应该怎么用,必须再去翻看源码,或者没有压根儿留神到这个组件导致重发开发。这个时候一个欠缺的组件库就很有必要了,能够保障开发者之间进行良好的合作。 组件库能够帮咱们解决以下问题: 业务组件跨我的项目复用,晋升开发效率对立代码实现,对立代码品质保障组件库文档提供清晰的应用形式和直观的展现成果组件库的组成 业务组件形成 业务组件库是基于根底组件库进行编写的,根底组件库是应用antd。咱们会对根底组件针对不同需要进行封装,达到能够间接援用无需二次开发的目标(比方:下拉抉择组件,咱们会将接口申请数据、选项含糊查问、多语言等封装到组件外部,无需二次开发,接口申请也不须要再散落到各个页面中)。 指标引⼊即可使⽤,⽆需⼆次开发欠缺的文档和组件成果演示,反对代码一键拷贝良好的代码品质:应用Jest进行单元测试,保障代码品质良好的编码标准和代码提交标准:ESLint、Husky、commit-lint等工具进行校验和拦挡依据代码提交主动生成ChangeLog组件成果演示反对编辑实时渲染(在文档中编辑组件,实时变更展现成果)开发计划 组件库开发周期 筹备组件库文档选型评审首批组件梳理开发本地预览调试本地构建Jest + @testing-library目录构造标准本地开发环境构建代码标准校验代码提交标准校验CR和公布标准TypeScript反对单元测试组件开发组件库文档生成首次公布公布和应用首次版本迭代降级在线拜访业务组件新增业务组件迭代组件库文档托管可视化构建页面区块和页面

August 26, 2021 · 1 min · jiezi

关于组件库:GrowingIO-Design-组件库搭建之组件开发

前言 在《GrowingIO Design 组件库搭建之开发工具》一文中介绍了搭建组件库的起因和应用的开发工具,这篇文章就来介绍组件库的配角:组件。先从组件的定义说起。 组件的定义 组件是标准化的、可调换的 UI 模块。它们封装了 UI 局部的外观和性能。想想乐高积木。乐高积木可用于建造从城堡到宇宙飞船的所有货色,组件能够拆开并用于创立新性能。组件通过将状态与应用程序业务逻辑隔离来实现互换性。这样,你能够将简单的屏幕分解成简略的组件。每个组件都有定义明确的 API 和可被 Mock 的系列状态。这容许组件被拆开和重组,以构建不同的 UI。 组建驱动 UI 后面明确了组件定义之后,如何从一个个组件构建出残缺的 UI。过程如下: 一次构建一个组件:隔离构建每个组件并定义其相干状态。从小处着手。组合组件:将小组件组合在一起以解锁新性能,同时逐步减少复杂性。组装页面:通过组合复合组件来构建页面。应用 Mock 数据模仿页面的难以达到状态和边缘状况。集成到我的项目中:通过连贯数据和连贯业务逻辑,将页面增加到您的应用程序。组件驱动 UI 的益处: 品质: 通过隔离构建组件并定义其相干状态,验证用户界面在不同场景中工作。耐用性: 通过在组件级别进行测试,将缺点准确到细节。它比测试屏幕工作更少,也更准确。速度: 通过重用组件库或设计零碎中的现有组件,更快地组装 UI。效率: 通过将用户界面分解成离散的组件,而后在不同的团队成员之间分担负载,并行化开发和设计。接下来就得介绍如何用代码实现组件了。但在此之前,先说说代码仓库的事。 代码仓库 从代码仓库的格调说起:Monolithic Repo(简称 Monolith)、Monorepo 和 Multirepo。 Monolith:所有代码都寄存在一个仓库中。Ant Design 组件库应用的就是此种形式,所有组件都在 components 目录下,每个组件独自目录。Monorepo:也是将所有的代码都寄存在一个仓库中,然而它能够蕴含 Monolith(比方一个目录对应一个 Monolith)。组件库中应用此种形式的是 Material Components for the web,所有组件都寄存在 packages 目录下,每个组件都是一个 package,并且对立发版。Multirepo:将代码分成多个局部,寄存在不同的仓库中。此种形式的代表是 react-component,每个组件都是独自仓库,每个组件都可独自发版。对于 GrowingIO Design 来说,一方面是做不到 Material Design 那样对立发版,有些简略组件开发完后会长工夫不更新;另一方面是组件太多,应用 Multirepo 形式,导致仓库很多,保护老本太大。所以,GrowingIO Design 采纳了常见的 Monolith 格调,用一个仓库,不同组件放在不同目录下,并且最终只有一个 package。 组件目录 上一节中代码仓库格调抉择了 Monolith,也明确了不同组件放在不同目录下,思考到组件会随着迭代越来越多,有必要提前标准一下组件的目录构造,明确一下一个组件至多应该蕴含哪些文件。 ...

June 3, 2021 · 2 min · jiezi

关于组件库:从零到一搭建react业务组件库

在理论我的项目中,咱们经常会遇到这样的一些场景:比方当初须要做一个下载报表的性能,而且这个性能在很多页面都有,下载的也是同类型的报表,如果在每个页面都去写反复性能的代码显得特地冗余,可不将其封装成一个组件多出调用呢?只不过这个组件跟咱们常见的一些根底组件有些区别,次要区别在于这个组件外头蕴含了业务逻辑,咱们称之为“业务组件”,这类组件是专门为了进步开发效率衍生进去的一种计划,这个组件库可能由专门保护组件库的人来保护,也可能是单个项目组本人的业务组件库。废话不多说,咱们来着手实操一下: 初始化我的项目应用lerna初始化工程,Lerna 是一个优化应用 git 和 npm 治理多包存储库的工作流工具,用于治理具备多个包的 JavaScript 我的项目。 将大型代码库拆分为独立的独立版本包对于代码共享十分有用。 然而,在许多存储库中进行更改是麻烦和难以跟踪的事件。为了解决这些(和许多其余)问题,一些我的项目将它们的代码库组织成多包存储库。 像 Babel、React、Angular、Ember、Meteor、Jest 等等。 首先应用 npm 将 Lerna 装置到全局环境中: 举荐应用 Lerna 2.x 版本。 npm install --global lerna接下来,咱们将创立一个新的 git 代码仓库: git init pony-bre-component && cd pony-bre-component并与github近程仓库关联 get remote add origin xxx当初,咱们将上述仓库转变为一个 Lerna 仓库: lerna init另外,我的项目须要装置react、react-dom、typescript、@types/react、@types/react-dom yarn add typescript react react-dom @types/react @types/react-domnpx typescript --init 在根目录生成tsconfig.json你的代码仓库目前应该是如下构造: pony-business-component/ packages/ 寄存每一个组件 package.json lerna.json lerna配置 tsconfig.json typescript编译配置文件lerna.json: { "packages": [ "packages/*" ], "version": "0.0.0"}package.json: ...

May 2, 2021 · 4 min · jiezi

你期待的微信小程序表格组件来咯

背景在做H5开发中表格table是最常见的标签,如此好用的标签在微信小程序中却没有,无奈,叹息,绝望!!! 奔着利国利猿的使命,我*开始了造轮之路。 功能主要用于展示大量结构化数据。 支持分页,自定义操作,长表格宽表格滚动等功能。 实现前言 暴露必要属性例如表头,数据。支持外部样式控制表格。手机端的列表较轻暂时不需要暴露事件。细节 通过properties暴露了三个属性官方说明 Component({ properties: { list: { // 表格数据 type: Array, value: [] }, headers: { //表头 type: Array, value: [] }, hasBorder: { // 表格中间边框 type: String, value: "no" }, height: { //table的高度 type: Number || String, value: '' }, width: { type: Number, value: 0 }, tdWidth: { type: Number, value: 35 } }})通过externalClasses支持外部样式官方说明 /*s-class-header // 外部定义表头样式s-class-row // 外部定义行数据样式*/Component({ externalClasses: ['s-class-header', 's-class-row']})index.wxml文件通过嵌套循环动态渲染表格<view class="table table-noborder"> <view class="tr thead s-class-header"> <view wx:for="{{headers}}" class="td td-{{hasBorder}}border">{{item.display}}</view> </view> <block wx:for-item='i' wx:for="{{list}}"> <view class="tr s-class-row"> <view wx:for-item='j' wx:for="{{headers}}" class="td td-{{hasBorder}}border">{{i[j['text']]}}</view> </view> </block> </view>index.wxss 使用者对于很个性的样式可以自行修改源代码index.wxss文件.table { border: 1px solid #ccc; font-size: 28rpx; background: #fff; border-right:none;}.table-noborder { border-right:1rpx solid #ccc;} .tr{ display: flex;} .td { text-align: center; border: 1px solid #ccc; display: inline-block; border-bottom: none; flex: 1; padding: 16rpx; border-left: none;}.td-noborder{ border-right: none;} .thead .td{ border-top: none; padding: 16rpx; font-weight: bold;}#### 快速上手 ...

October 16, 2019 · 1 min · jiezi

前端物料中台建设

我在上一篇的文章大BU级别的"前后端分离"实践中提出了我们当前的前端团队中存在一些问题以及解决思路,并且在其中详细地写出了统一视图服务的实现思路和收益。这篇文章主要写关于前端迭代及上下游协作效率我们是如何解决的。 背景我们的目的是提升前端迭代及上下游的协作效率,我们从四个出发点开始讲起: 团队负责的业务越来越读,如何提高资源、组件及代码的复用率,提升整体研发效率;提升项目的上下游协作效率,涉及到从UE到UI到FE再到QA的整个流程,这需要很强的推动力和足够的说服力;提升人效比,一人顶三人,提升项目中前端开发人员的人效比,让前端做的更快、更多、更好;最后是将整体方法进行梳理,把提效的这部分能力应用在web、wap、小程序中,实施中台化。 解决思路 首先,建设前端物料体系,重新定义和统一前端的开发标准,建设前端物料资源体系,其中包括设计和单元测试等资源;第二,实行工具化管理,完善工程体系,统一前端的开发流程和技术栈,保证资源复用率;最后也是最重要的就是渐进式开发,因为它决定了物料完成之后能不能达到最佳的复用率。 整体架构 问:什么是物料?答:可按照规范进行标准化构建,并且可以在不同项目,不同团队,不同成员之间复用的任意资源。我们把这类资源统称为物料。参与物料资源生产和消费的对象共有四个:开发者、使用者、设计者、产品/运营。为此,物料中台提供了标准化的物料资源,其中包括项目的基础框架、组件库、区块和模板。基础框架是项目的样板框架也就是俗称的boilerplate,组件库是基于部门内设计同学提出的Union Design设计规范开发前端组件库,它同时支持web和小程序两个宿主环境。区块可以简单理解为组件的拼装集合,它比组件库提供了更上层的业务封装能力,但是这也让它变得没有组件库那么地纯粹;模板就是各种站点的样式模板,其中整合了前面所提到的基础框架+组件库+区块等各种资源。让开发者可以最大限度地减少工作量。 图中的中间部分是可被支持的宿主环境,包括Web端、移动端及小程序。Web端可以支持TypeScript+Vue/React框架模式进行开发,移动端支持VW/REM布局方式,同时也支持Hybrid模式进行开发,具体文章请参考端动态化方案详细设计。另外由于业务原因,小程序目前支持微信小程序和智能小程序两种。 最下面是物料中台提供的工程化体系,提供了CLI工具和GUI工具。CLI工具用于在前端项目开发中,让FE可以便捷地对物料进行生成和消费;此外物料中台还提供了GUI工具,让物料的消费方可以通过拖控件的方式,对项目进行快速地原型落地和模板设计,里面具体的细节请等待后续的文章更新。 我们和设计同学一起推出了物料相关的设计资源,其中就包括Union Design设计规范。为了降低物料在项目中的落地阻力,物料中台还提供了完善学习资源,包括文档、教程,也会定期组织培训和分享。 最后,在整体上实现了物料中台的功能。 组件库设计我们在进行组件库设计是主要考虑了两个方面: 组件分级 基础UI组件复合组件业务组件组件边界 越界操作副作用侵入性循环依赖首先对组件进行分级,根据对业务的侵入性和纯粹性(复用程度)为分界点,拆分为三级,如下图: 如图中表示,越往下业务侵入性越高,抽象程度越低。越往上复用程度和纯粹性越高,同时抽象程度也越高。 组件库设计的关键就是组件的边界限制,每个组件都是非常独立的且不可再拆分的最小单元。首先是禁止组件的越界操作,只让它处理份内的事情,对外部的事情不能染指半分;第二是副作用,禁止(尽可能的少)有副作用,如果了解过函数式编程,就会知道副作用的各种优缺点;第三是侵入性,禁止纯粹的木偶组件(组件库中的每个组件都是纯粹的木偶组件)对业务的侵入性,因为侵入性越高复用率越低,组件库对于其他人也就越难用;最后是禁止组件内部的循环依赖。 最终实现 最终实现中,整体分为四层,最下面是技术实现,往上是依赖的设计资源,再往上就是组件库提供的五种基础组件,包括基本操作、表单、视图、导航和数据处理等。最上层则是接入的业务方。自下而上地完成了整个前端业务方向的组件库方案。 上下游协作对上下游协作效率优化的流程中最核心的就是效率提升和物料复用。 效率提升 交互设计单元测试回归成本物料复用 物料共享生成和消费业务迁移渐进式开发整体流程如下图: 在整体协作流程中主要包含两条操作流程,物料管理和物料使用。 物料管理的功能是给物料开发者使用的,负责物料对不同平台的支持,创建,生成和列表管理,可以在管理列表中对自己上传物料进行消费。 对于物料的消费,提供物料实时预览、下载、使用、和源代码查看功能。使用物料时会自动生成CLI命令,在终端中执行命令就可以在项目中使用此物料。 另外,也可以将项目中的某些功能抽离为物料,供其他项目使用。以此实现可持续迭代和渐进式开发。这样就完成物料资源在不同团队,不同项目,不同成员之间的共享和复用,提升前端的整体协作效率。 整体收益 内部接入6个项目;在公司内部NPM中开源了2个组件库;在BU内部共推出了4款产品,分别是Union Design设计规范、@baidu/union-design、@baidu/union-design-wechat和marble-cli/GUI工具; 在代码复用率方面,项目基础框架为46.1%,业务逻辑为21.87%;全新开发一个项目迭代周期缩短23.8%,迭代的项目缩短21.4%; 最后有任何疑问请联系作者

August 20, 2019 · 1 min · jiezi

GrapeCity-Documents-for-Excel-文档API组件-V22-新特性介绍

GrapeCity Documents for Excel 文档API组件 V2.2 正式发布,本次新版本包含诸多重量级产品功能,如:将带有形状的电子表格导出为 PDF、控制分页和电子表格内容、将Excel电子表格的特定页面打印为PDF、在工作簿之间剪切和复制工作表等。 作为一款适用于 .NET 和 Java 6.0+ 标准的文档API组件,GrapeCity Documents for Excel 通过编码的方式,无需依赖 Microsoft Excel ,即可超快批量操作 Excel 文件,与纯前端表格控件 SpreadJS 结合使用,可同时在 Web 端实现 Excel 类数据展示、Excel 功能和布局样式,以及后端 Excel 导入导出等业务场景,使您开发的应用程序具备快速创建、加载、编辑、导入/导出大型 Excel 文档的功能模块。 点击此处,下载最新版 GrapeCity Documents for Excel (Java) 点击此处,下载最新版 GrapeCity Documents for Excel (.NET) 将带有形状的电子表格导出为 PDF使用 GrapeCity Documents for Excel,您可以将带有形状的电子表格导出为 PDF,这些形状包括箭头、线条、图片和一般默认形状(包括 MS Excel 的内置形状)。利用这一特性,开发人员可以创建更为有趣且丰富的 Excel 工作表。 导出的 PDF 中支持的形状属性包括: 填充样式线条样式形状与文本形状与图片旋转的形状翻转的形状分组的形状 .NET 平台帮助文档 | .NET 平台示例 | Java 平台帮助文档 | Java 平台示例 ...

July 16, 2019 · 5 min · jiezi

Vue组件库工程探索与实践构建工具篇

我们团队近期发布了移动端 Vue 组件库 NutUI 的 2.0 版,2.0 不是 1.0 的升级,而是一个全新的组件库。从 1.0 到 2.0 一路走来,我们积累了一些 Vue 组件库的开发经验,接下来的一段时间,我们将以系列文章的形式与大家进行分享,欢迎大家关注。作为《Vue组件库工程探索与实践》系列文章开篇之作,我们从“盘古开天地”说起吧。 从当年的静态页面到如今的 Web App,前端工程越来越复杂,对于一个稍大些的前端项目来说,代码都写在一起难以维护,团队分工协作也成问题。根据软件工程领域的经验,解决这些问题的一个可行思路就是代码的模块化,即对代码按功能模块进行分拆,封装成组件,而反过来讲,组件就是指能完成某个特定功能的独立的、可重用的代码块。 把一个大的应用分解成若干小的组件,而每个组件只需要关注于某个小范围的特定功能,但是把组件组合起来,就能构成一个功能庞大的应用。组件化的网页开发也是如此,就像搭积木,各个组件拼接在一起就组成了一个完整的页面。 组件化开发可大大降低代码耦合度、提高代码的可维护性和开发效率,同时有利于团队分工协作和降低开发成本。这种开发模式已日渐流行起来。 当前,前端开发领域最流行的三大框架 Vue、React、Angular 都推崇组件化开发,组件是这些框架中极为重要的概念和功能。 以 Vue.js 来说,组件 (Component) 可以说是其最强大的功能,它可以扩展 HTML 元素,封装可重用的代码。Vue.js 的组件系统让我们可以用这些独立可复用的小组件来构建大型 Vue 应用,几乎任意类型的 Vue 应用的界面都可以抽象为一个组件树。 如果我们把日常应用开发中常用的组件累积起来,后续的项目就可以复用这些组件,这对提高开发效率、降低开发成本有重要意义。 因此,一个前端团队拥有一个常用框架的组件库是十分必要的。 模块化与构建工具组件库自身就是一个大的工程,需要按照模块化开发思想进行模块划分。通常,在一个组件库里,组件、组件的样式文件、配置文件…都是模块,而最终我们需要把这些模块组合成一个完整的组件库文件,承担这种组装工作的就是打包构建工具。当下主流的库构建工具主要有 Rollup 和 Webpack 等。在说这些模块打包构建工具之前,我们先来了解一下目前主流的 JavaScript 模块化方案。 JavaScript 语言一直以来饱受诟病的一个地方就是它的语言标准里没有模块(module)体系,这对开发大型的、复杂的项目形成了巨大障碍。直到 ES6 时期,才在语言标准层面实现模块功能(ES6 Module)。在 ES6 之前,业界流行的是社区制定的一些模块加载方案,如 CommonJS 和 AMD 。而 ES6 Module 作为官方规范,且浏览器端和服务器端通用,未来一定会一统天下,但由于 ES6 Module 来的太晚,受限于兼容性等因素,可以预见的是今后一段时期内,多种模块化方案仍会共存。 ES6 Modue 规范:JavaScript 语言标准模块化方案,浏览器和服务器通用,模块功能主要由 export 和 import 两个命令构成。export 用于定义模块的对外接口,import 用于输入其他模块提供的功能。CommonJS 规范:主要用于服务端的 JavaScript 模块化方案,Node.js 采用的就是这种方案,所以各种 Node.js 环境的前端构建工具都支持该规范。CommonJS 规范规定通过 require 命令加载其他模块,通过 module.exports 或者 exports 对外暴露接口。AMD 规范:全称是 Asynchronous Modules Definition,异步模块定义规范,一种更主要用于浏览器端的 JavaScript 模块化方案,该方案的代表实现者是 RequireJS,通过 define 方法定义模块,通过 require 方法加载模块。一些“上年纪”的国内前端老艺人们可能还会提到 CMD 规范,它是 SeaJS 在推广过程中对模块定义的规范化产出,只是 SeaJS 并未实现国际化,且项目在2015年就已宣布停止维护了,算不上当前主流模块化方案。介绍完主流模块化规范,我们再回过头来看 Rollup 和 Webpack 这两个模块打包构建工具。 ...

July 5, 2019 · 3 min · jiezi

轻量的移动端React组件库

移动端React组件库重新设计了Form那块组件,让数据校验变得更简单。欢迎提出更多优化建议,如有兴趣参与该项目,请邮件至:saytxk@gmail.com (-> . ->) 没错,我就是来骗 Star 滴。 项目地址: https://github.com/rc-mobile/rcm-mobile演示页面: https://rc-mobile.github.io/rcm-mobile/使用说明1.创建一个项目(走模版创建,无需任何配置,尚未开源)走模版创建的项目,无需下面配置操作,开箱即用。敬请期待... 2.依赖安装npm i -S rcm-mobile # 下载依赖3.初始HTML解决不同机型的多倍屏问题,通过设置视网膜显示屏来达到统一的目的。 组件尺寸大小都是基于 rem 开发,可以灵活调整以适用想要适配的视网膜显示屏通用做法:一倍视网膜显示屏方案<!DOCTYPE html><html lang="cn"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> <meta name="apple-mobile-web-app-capable" content="yes" /> </head> <body></body></html>自定义:多倍视网膜显示屏 第一步:确定视网膜显示屏倍数,如现在设成 2倍第二步:初始化rem的大小,html{font-size: 32px}。即浏览器默认的文字大小(16px) * 视网膜显示屏倍数第三步:恢复body下的文字大小,body{font-size: 16px}<!DOCTYPE html><html lang="cn" style="font-size: 32px;"> <head> <meta charset="utf-8"> <meta name="apple-mobile-web-app-capable" content="yes" /> <script> (function () { var phoneScale = parseInt(window.screen.width) / 750 document.write('\<meta name="viewport" content="width=750, minimum-scale=' + phoneScale + ', maximum-scale=' + phoneScale + ', user-scalable=no, viewport-fit=cover">') })() </script> </head> <body style="font-size: 16px;"></body></html>4.全量使用(不推荐)组件使用实例: ...

June 15, 2019 · 1 min · jiezi

Vant-20-发布持之以恒不乱节奏

持之以恒,不乱节奏,对于长期作业实在至为重要。一旦节奏得以设定,其余的问题便可迎刃而解。 -- 村上春树维护组件库就像跑马拉松,开源只是从起点迈出第一步,困难的是持之以恒地跑下去。 自 2017 年开源以来,Vant 已经跑了两年多时间,未曾停歇。在 2018 年我们发布了 1.0 版本和小程序版,并持续迭代了 100 多个小版本。 对于版本迭代,我们更倾向于小步快跑,保持每周更新一个版本的节奏,及时解决大家的问题和需求。但是写代码偶尔也需要一点"仪式感",因此我们集中开发了一个多月的时间,将社区中反馈较多的需求一网打尽,为大家带来本次发布的 Vant 2.0 版本。 回顾在介绍 2.0 版本之前,先看一下我们到目前为止的成绩吧~ 发布 220 个版本合并 2100 个 PR处理 3000 个 issue累计 18000 个 star累计 1000000 下载量(npm & cnpm)上面是 vant 和 vant-weapp 两个仓库的合并数据。值得一提的是 Vant 的 issue 处理比例在 98% 左右,大部分 issue 都会在 1~3 天内得到回复,感谢所有帮助我们回复 issue 的同学们。 内容介绍新组件在 2.0 版本中,我们引入了社区中呼声最高的四个组件,分别是: Image 图片,类似于小程序原生的 Image 标签,支持多种图片裁剪模式IndexBar 索引栏,通讯录中的字母索引栏,用于长列表快速索引Skeleton 骨架屏,在待加载区域展示的占位区块,提供界面加载过程中的过渡效果DropdownMenu 下拉菜单,用于列表的分类选择、筛选及排序 新文档文档方面,我们重新设计了文档站点,用卡片的方式组织段落,更加直观。对一些较为复杂的组件,我们对示例进行细粒度的拆分,添加更多的用法介绍,以帮助大家更快地上手使用。 此外,文档站点也支持了搜索和版本切换。 样式定制移动端 UI 风格多变,对组件的可定制性要求较高。从 2.0 版本开始,Vant 中的所有组件都支持通过 Less 变量进行样式定制。同时我们新增了多个样式相关的 Props,便于快速定制组件风格。 ...

June 13, 2019 · 1 min · jiezi

如何开发一个基于 Vue 的 ui 组件库(二)

遗留问题书接上回,说道利用 sideEffects 字段,只需读取源文件即可实现按需加载,还有个坑忘了说…文档中的样式打包后会丢失…因为我们只注意到了作为组件库的源代码,而忘了我们的文档是通过 vuepress 编译,即底层也是基于 webpack 进行打包。所以 sideEffects 中也要加上文档中的文件。组件文档该写些什么?在编写组件库文档时,有两个必不可少的部分。组件预览,最好有相应的代码组件 api,即 props、events、slots 等接口和参数的说明如何同时展示 demo 和 code?最【一力降十会】的方法当然就是复制粘贴一把梭…这样实现简单是简单,不过维护时要同时改至少两份代码。比如 vant 的展示文档 和 cube-ui 的展示文档。进阶一点儿的方法就是嵌入 Codepen、JSFiddle 或 CodeSandbox 的 iframe。但是组件库中一般有大量的组件,不可能为每个组件都维护一份小代码片段,并且别忘了这可是三个平台(硬点一个吼不吼啊~?)。因此各种组件库使用的最多的方法还是自己编写组件。(下一小节详解)当然也有例外比如 vux 只有 demo 没有 code。业界的文档组件最普遍的方式还是基于 markdown-it,将自己的 vue 组件插入文档中。muse-ui 的 demo-block 组件muse-ui 的 markdown-it 配置ant-design-vue 的 demoBox 组件ant-design-vue 的 markdown-it 配置element 的 demo-Block 组件element 的 markdown-it 配置比较有意思的是 mand-mobile 的文档编写方式。demo 的文档放在组件目录中,然后由 Doc 组件读取各个组件的 demo。mand-mobile 的展示文档mand-mobile 的 Doc 组件那么对于我们使用 vuepress 编写文档的开发者来说咋办咧?在 vuepress 中展示 demo 和 code首先让我们来分析一下:这两份重复的代码应该以谁为主?即我们应该只编写 demo 的代码还是 code 的代码?先有鸡还是先有蛋?物质决定意识还是意识决定物质?至少在编写 demo 和 code 这个问题中,我认为 demo 才是“本源”,为什么?这是最普遍的方式,各大组件库基本这么干这是最自然的方式,因为 vuepress 会编译 md 中的 vue 组件若是反过来,文档中以 code 为主,再由 code 生成 demo 会有一些不便如何预处理代码:babel、scss 等?如何插入生成的组件到文档中?感兴趣的话可以看看这个插件 vuepress-plugin-demo-block一开始我只在 .vuepress/components/ 中建了个组件自娱自乐,后来看到了 vuepress-plugin-demo-block,但觉得由 code 生成 demo 有点儿绕。于是自己搞了个插件 vuepress-plugin-demo-code,有需要的读者老爷可以自取~组件的 api 文档解决了 demo 和 code 的重复编写问题,接下来是另一个令人无发可脱的问题:如何自动生成并同步 .vue 组件的 api 文档?手动维护肯定是不行的,还好有一个炒鸡好用的库 vuese。vuese 会基于 ast 分析你的 .vue 文件,提取其中的 props、events、slots 等接口和参数的说明。为了将其集成到 vuepress 中,我又整了个 markdown-it 插件 markdown-it-vuese。只需使用以下的语法在导入已经存在的 *.vue 文件的同时,使用 Vuese 自动生成文档。<vuese以上 to be continued…参考资料muse-ui 的 demo-block 组件muse-ui 的 markdown-it 配置ant-design-vue 的 demoBox 组件ant-design-vue 的 markdown-it 配置element 的 demo-Block 组件element 的 markdown-it 配置vux 的展示文档vant 的展示文档cube-ui 的展示文档mand-mobile 的展示文档mand-mobile 的 Doc 组件vuepress-plugin-demo-codevuepress-plugin-demo-blockvuesemarkdown-it-vuese ...

April 1, 2019 · 1 min · jiezi

针对前端开发可重用组件并发布到NPM

翻译:疯狂的技术宅原文:https://www.smashingmagazine….本文首发微信公众号:jingchengyideng欢迎关注,每天都给你推送新鲜的前端技术文章摘要:本文着眼于使用具有内置功能和样式的组件来扩充HTML。 我们还将学习如何通过 NPM 使这些自定义元素在项目中得到重用。即便是最简单的组件,人力成本也可能很高。 UX 团队进行要可用性测试。 涉及到的利益相关者必须对设计签字确认。之后是开发人员进行 AB 测试,可访问性审计,单元测试和跨浏览器检查。 一旦解决了这个问题,你就不想再次重复这项工作了。 通过构建可重用的组件库(而不是从头开始构建所有内容),我们就可以不断复用过去的工作,避免重新审视已经解决的设计和开发过程。构建组件库对于像Google这样的公司尤为重要,他们拥有很多具有相同品牌的网站。 通过把 UI 编码为可组合小部件,这些大公司既可以减少开发时间,又可以实现跨项目的可视化和用户交互设计的一致性。在过去几年中,人们对样式指南和模式库的兴趣不断增加。由于开发人员和设计师一般都分布在多个团队中,所以大公司需要寻求实现一致性的方法,比如提供简单的颜色样本。不过对于我们来说,可以比他们做得更好。 我们需要的是易于分发的代码。共享和重用代码手动复制和粘贴代码很容易。但是把代码保持在最新版是维护上的噩梦。所以许多开发者依赖包管理器来跨项目重用代码。 尽管名字是 Node Package Manager, 但是它已成为前端包管理的独一无二的平台。 目前在 NPM 上注册的包超过700,000个,每月下载数十亿次。 含有 package.json 文件的任何文件夹都可以作为可共享包上传到NPM。 虽然NPM主要与JavaScript相关联,但包中也可以包含 CSS 和标记。 NPM使重用变得很容易,这对更新代码尤为重要:你无需在各种地方修改代码,所做的是只需在包中更新代码即可。标记存在的问题使用 import 语句可以对Sass和Javascript 进行轻松移植。 模板语言赋予了 HTML 相同的能力 —— 模板能以局部形式导入到 HTML 的其他片段。 比如你可以只需为页脚编写一次标记,然后将其包含在其他模板中即可。 另一种方法是复制并粘贴标记,并只对样式和 javascript 使用NPM。这是英国“金融时报”在 Origami 组件库中用到的方法。Alice Bartlett在她的演讲中总结道:“你不能让它更像是 Bootstrap 吗?”,“并没有什么好办法能让人们在他们的项目中包含模板”。Ian Feather谈到他在 Lonely Planet 维护组件库的经历,重申了这种方法存在的问题:“一旦复制了这些代码,他们基本上就会削减一个需要无限期维护的版本。当复制工作组件的标记时,它具有到该点的CSS快照的隐式链接。 如果你随后更新模板或重构CSS,则需要更新分散在你网站周围的所有模板的版本。“解决方案:WEB组件Web组件通过在 JavaScript 中定义标记来解决这个问题。 组件的作者可以自由地修改标记、CSS 和 Javascript。 组件的使用者可以在这些升级中受益,无需手动修改项目代码。 只需要通过在终端的敲出简短的 npm update 命令,就可以在项目范围内更新到最新版本。当然前提是组件的名称及其 API 需要保持一致。安装Web组件就像在终端中键入 npm install component-name 一样简单。 Javascript 可以包含在 import 语句中:<script type=“module”>import ‘./node_modules/component-name/index.js’;</script>在CodePen上的代码演示:https://codepen.io/cssgrid/pe…在前端开发中,以组件为中心的方法已经变得无处不在,Facebook 的 React 框架就使用了这种方法。考虑到在现代前端开发工作中框架的普遍性,许多公司已经在用他们选择的框架构建了组件库。这些组件只能在该特定框架内重用。IBM Carbon Design System的一个组件。 仅能用于 React 应用。其他在 React 中构建的组件库的主要案例包括Atlassian 的 Atlaskit 和 Shopify 的 Polaris。对规模较大的公司来说,很少有统一的前端,从一个框架转到另一个框架的重新布局并不罕见。各种框架你方唱罢我登场。 为了在项目中实现最大程度的潜在重用,我们需要与框架无关的组件。通过在npmjs.com对组件的搜索结果揭示了一个支离破碎的Javascript生态系统。随着时间的推移,框架也在不断变化。“多年来我使用 Dojo、Mootools、Prototype、jQuery、Backbone、Thorax 和 React 构建了 Web 应用……我希望能把我开发的 Dojo 组件用到现在的 React 应用中。“—— 谷歌工程总监Dion Almaer当我们谈论Web组件时,我们讨论的是自定义元素与 shadow DOM 的组合。 自定义元素和 shadow DOM 是W3C DOM 规范和 WHATWG DOM 标准的一部分 —— 这意味着 Web 组件是 Web 标准的一部分。自定义元素和 shadow DOM 最终会实现跨浏览器支持。 通过使用原生 Web 平台的标准部分,我们确保自己的组件能够在前端重组和不断重构的快速变化周期中生存下来。 Web组件可以与任何一种模板语言和前端框架一起使用 —— 它们是真正交叉兼容和可互操作的。 从 Wordpress 博客到单页应用程序,可以在任何场合下使用。Rob Dodson的 Custom Elements Everywhere 项目记录了 Web 组件与各种客户端 Javascript 框架的互操作性。 这里面 React 出现的异常值,希望能在 React 17 中解决。制作Web组件定义一个自定义元素生成 made-up-tag 标记并使其内容显示在页面上。<made-up-tag>Hello World!</made-up-tag>HTML 被设计为能够容错。即使不是有效的HTML元素,它的内容也会被呈现。 并没有一个很好的理由这样做 —— 偏离标准化标签在传统上是很差劲的做法。 但是通过用自定义元素 API 定义新的标记,我们就可以用具有内置功能的可重用元素来扩充HTML。 创建自定义元素很像在 React 中创建一个组件 —— 但在这里是扩展了 HTMLElement 。class ExpandableBox extends HTMLElement { constructor() { super() } }构造函数中的第一个语句必须是对 super() 的无参数调用。构造函数应该用于设置初始状态和默认值,以及设置事件侦听器。 需要使用其 HTML 标记的名称和对应的类的元素定义新的自定义元素:customElements.define(’expandable-box’, ExpandableBox)把类名大写是一种惯例。 HTML 标记的语法不仅仅是一种约定,如果浏览器想要实现一个新的HTML元素,并且想把它称为可扩展框怎么办?为了防止命名冲突,不是最新标准的 HTML 标记要包含破折号。 所以自定义元素的名称也 必须 包含破折号。customElements.define(‘whatever’, Whatever) // 无效customElements.define(‘what-ever’, Whatever) // 有效定制元素生命周期API 提供了四种自定义元素响应 —— 可以在类中定义函数,这些函数会自动调用来响应自定义元素生命周期中的某些事件。当自定义元素添加到 DOM 时会执行 connectedCallback。connectedCallback() { console.log(“custom element is on the page!”)}这包括用 Javascript 添加元素:document.body.appendChild(document.createElement(“expandable-box”)) // “custom element is on the page"以及简单地在页面中包含带有 HTML 标记的元素:<expandable-box></expandable-box> // “custom element is on the page"所有涉及到获取资源或渲染的工作都应该在这里。从 DOM 中删除自定义元素时,将运行 disconnectedCallback。disconnectedCallback() { console.log(“element has been removed”)}document.querySelector(“expandable-box”).remove() //“element has been removed"当自定义元素被采用到新文档中时,将会运行 adoptedCallback 。 你可能不需要太关心这个问题。在添加、更改或删除属性时运行 attributeChangedCallback 。 它可以用于监听标准化本机属性(如 disabled 或 src )的更改,以及我们定义的任何自定义属性。 这是自定义元素最强大的功能之一,因为它可以创建用户友好的 API。定制元素属性因为有很多 HTML 属性,所以当任何属性发生变化时,浏览器都不会浪费时间去调用我们的 attributeChangedCallback ,因此需要提供一个我们想要监听的属性更改列表。对于这个例子,我们只对一个感兴趣。static get observedAttributes() { return [’expanded’] }所以现在 attributeChangedCallback 只会在我们更改自定义元素上expanded属性的值时被调用,因为它是我们列出的唯一属性。HTML 属性可以有相应的值(例如 href,src,alt,value 等),而其他值可以是true或false (例如 disabled, selected, required)。 对于具有相应值的属性,我们将在自定义元素的类定义中包含以下内容。get yourCustomAttributeName() { return this.getAttribute(‘yourCustomAttributeName’);}set yourCustomAttributeName(newValue) { this.setAttribute(‘yourCustomAttributeName’, newValue);}对于例子中的元素,其属性为 true 或 false,因此定义 getter 和 setter 会有所不同。get expanded() { return this.hasAttribute(’expanded’)} // setAttribute的第二个参数是必需的,所以我们将用一个空字符串填充set expanded(val) { if (val) { this.setAttribute(’expanded’, ‘’); } else { this.removeAttribute(’expanded’) }}既然已经处理了样板文件,我们可以使用 attributeChangedCallback 。attributeChangedCallback(name, oldval, newval) { console.log(the ${name} attribute has changed from ${oldval} to ${newval}!!); // 每次属性被更改时执行某些操作}配置 Javascript 组件会涉及将参数传递给 init 函数。 通过使用 attributeChangedCallback ,可以创建一个可以使用标记配置的自定义元素。Shadow DOM 和自定义元素可以单独使用,你可以找到对自己有用的自定义元素。 与 shadow DOM 不同,它们可以是 Polyfill。 不过它们配合得很好。使用SHADOW DOM附加标记和样式到目前为止,我们已经处理了自定义元素的行为。 但是关于标记和样式,我们的自定义元素相当于空的无样式 <span> 。 要将HTML和CSS封装为组件的一部分,还需要附加一个shadow DOM。 最好在构造函数中执行此操作。class FancyComponent extends HTMLElement { constructor() { super() var shadowRoot = this.attachShadow({mode: ‘open’}) shadowRoot.innerHTML = &lt;h2&gt;hello world!&lt;/h2&gt; }不要为理解模式的含义担心——你必须包含它的样板,但你几乎总是想要 open。 这个简单的例子组件将只呈现文本“hello world”。 与大多数其他 HTML 元素一样,自定义元素可以包含子元素 —— 但默认情况下不是。 到目前为止,前面的自定义元素还不能将任何子元素渲染到屏幕上。 要显示标记之间的内容,还需要用到 slot 元素。shadowRoot.innerHTML = &lt;h2&gt;hello world!&lt;/h2&gt;&lt;slot&gt;&lt;/slot&gt;我们可以用样式标记将 CSS 应用于组件。shadowRoot.innerHTML = &lt;style&gt;p {color: red;}&lt;/style&gt;&lt;h2&gt;hello world!&lt;/h2&gt;&lt;slot&gt;some default content&lt;/slot&gt;这些样式仅适用于组件,因此我们可以自由地使用元素选择器,而不会影响页面的任何其他内容。 这就把编写 CSS 的过程变得非常简单,使 BEM 这样的命名约定变得不必要。通过 NPM 发布组件NPM 包通过命令行进行发布。 打开一个终端窗口并切换到你想要变成可重用包的目录中,然后在终端中键入以下命令:如果你的项目还没有 package.json, npm init 将会引导你创建一个。npm adduser 把你的机器链接到你的 NPM 帐户。 如果你还没有注册,它将为你创建一个新的账号。npm publish如果一切顺利的话,在 NPM 列表中会出现你的组件,可以在你自己的项目中安装和使用 —— 并与全世界共享。Web组件API并不完美。自定义元素目前还无法在表单提交中包含数据。 渐进式增强并不是很好,对可访问性的处理并不怎么容易。尽管最初在 2011 年宣布,但浏览器还没有普遍支持。 Firefox 将在今年(2018)晚些时候提供支持。 尽管如此,一些备受瞩目的网站(如 Youtube )已经在使用它们。 尽管目前还存在缺点,但对于普遍可共享的组件而言,它们是唯一的选择,并且在未来它们提供的令人兴奋的新功能非常值得期待。本文首发微信公众号:jingchengyideng欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章 ...

February 18, 2019 · 2 min · jiezi

为什么自己写的组件库被引用总是报错——详解webpack的library和libraryTarget

如果我们仅仅是实现一个项目,我们大概率不会关注到webpack output中的这两个属性。但是如果我们是实现一个组件库,那么这两个属性就变得至关重要了。本文从自己之前遇到的一个问题说起,继而引申出library和libraryTarget属性。1. 故事起源当我自己开始写第一个组件库的时候,很快我就撸好了框架的代码,然后我兴致冲冲的把我的组件库引入到我的项目中,我记得那时候我是这么写的:组件库:import Feeds from ‘@/components/feeds/index’;export { Feeds,};主项目:import Feeds from ‘@/tencent/newsH5Ad’;// 一些其他代码<Feeds data=‘xxx’>然后我就收获了一个报错,Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: null。啊?难道是我的最终输出代码有问题?我检查了一下最终输出的代码,没有问题,Feed组件的代码也在里面。这个问题我查了很久,都没有答案,最后才发现是webpack打包的问题。这就涉及到了本文的主角,library和libraryTarget。2.2. library和libraryTarget我们都知道,webpack可以将不同的模块化方式(commonjs, AMD, CMD, ES6 Module)的代码打包。那我们打出来的代码包其实也可以按不同的模块化方式生成,所以:libraryTarget就是配置webpack打包内容的模块方式的参数而library就是webpack打包内容的名字所以library规定了组件库返回值的名字,libraryTarget规定了返回值的编码格式。libraryTarget的配置选项可以分为四大类:2.1 按不同的模块方式生成也就是我们这个问题的解决方法,由于我写的是一个React的UI组件库,所以我们需要commonjs的模块方式。因此只需要在webpack.config.js中配置这一项即可:module.exports = { entry: ‘./src/index.js’, output: { filename: ‘index.js’, // library: ‘MyLibrary’, // 模块名称 libraryTarget: ‘commonjs2’, // 输出格式 }, // 其他代码}事实上,你可以选择的选项有:commonjs/commonjs2: 将你的library暴露为CommonJS模块amd: 将你的library暴露为amd模块umd: 将你的library暴露为所有的模块定义下都可运行的方式其中AMD和UMD需要指定library,如果不声明组件库则不能正常运行。这是为了在浏览器上通过script标签加载时,用AMD模块方式输出的组件库可以有明确的模块名。如:define(“MyLibrary”, [], function() { return entry_return; // 此模块返回值,是入口 chunk 返回的值});注意:commonjs和commonjs2几乎相同,只不过commonjs只包含exports,而commonjs2还包含module.exports,所以直接使用commonjs2即可。2.2 生成为一个变量libraryTarget的默认值是var,顾名思义,就是将组件库入口起点的返回值生成一个变量。如:var MyLibrary = entry_return;也可以选择‘assign’,那样的话将默认生成和一个全局的变量。不管是var还是assign,都需要设置library的名称,否则就会报错。2.3 生成一个为一个对象的属性和第二种情况差不多,只不过会把这个变量赋值给某个对象,作为它的一个属性存在。可以选择的选项有:this: 返回值成为this的一个属性window: 返回值成为window的一个属性global: 返回值成为global的一个属性例如:this[“MyLibrary”] = entry_return;window[“MyLibrary”] = entry_return;global[“MyLibrary”] = entry_return;可以看到,这种情况下也必须指定library的名字。2.4 异步生成方式在这种情况下,libraryTarget的值为‘jsonp’,组件库入口起点的返回值,会被包裹到一个jsonp包装容器中,并配合webpack的externals使用——组件库的依赖由externals指定。如:MyLibrary(entry_return);3. 总结本文介绍了webpack中libraray和libraryTarget的相关内容,解释了为什么不设置它们时使用webpack打包出来的组件库会有问题。一般情况下,作为vue或者react组件库,libraryTarget在commonjs2,amd,umd中三者择其一即可。参考文献《webpack文档》 ...

January 21, 2019 · 1 min · jiezi

基于react的高度过渡组件

开发中,最麻烦的过渡效果就是高度过渡。因为过渡效果需要设置一个起始状态和结束状态,但是对于web中的元素来说,容器高度大部分是根据内部元素自动撑起来的,这时很难去设置一个稳定的过渡高度。所以我写了一个基于react的组件来自动完成高度过渡这一实现。使用方法:首先npm install auto-height-transition -S具体使用:import { TransitionWhenHeightChange, TransitionWhenToggle} from ‘auto-height-transition’;// 在元素显示隐藏时进行过渡<TransitionWhenToggle duration={300} timeFunction={’ease’}> { this.state.show && ( <div> placeholder<br/> placeholder<br/> placeholder<br/> placeholder<br/> </div> ) }</TransitionWhenToggle>// 设置一个最小高度,然后切换进行过渡。通常用于 查看更多 显示详情<TransitionWhenHeightChange height={this.state.shouldCollapsed ? 20 : null} duration={300} timeFunction={’ease’}> <div> placeholder<br/> placeholder<br/> placeholder<br/> placeholder<br/> </div></TransitionWhenHeightChange>github地址:auto-height-transition

December 23, 2018 · 1 min · jiezi