vue组件库开发

为何要进行组件库开发

如果你所在的公司对于页面的样式没有什么要求,那么你只要随便拿一个组件库来用就行了,比如element、iView等等,不用再重复造轮子了;
如果你目前只有个人用一个组件,或者是只对个别组件有要求,那么只要在你的工程里面开发一个.vue单文件组件就可以了;如果你的团队想要一个更加快速的开发方式,希望有一套一类应用的标准,并且对组件的样式有较高的要求,那么你就需要开发一个组件库了。

正确的学习方式

我觉得我写完这篇文章以后,大家看完可能只是能按部就班地开发一个组件库而已,而且具体的记忆和理解不是很深,所以我觉得正确的方式应该是站在巨人的肩膀上,比如去查看element组件库的源码,去了解他的文件组织方式,文档是如何管理的,主题文件是如何管理的,以及一些复杂组件是如何实现的。接下来,我们就进入正题。

步骤

我们来理一下整个步骤:

  1. 创建项目
  2. 调整项目结构
  3. 编写组件
  4. 使用vue-cli-service库模式打包编译
  5. 发布到npm

创建项目

# 创建目录
mkdir frog-ui
# 切换目录
cd frog-ui
# 初始化项目
vue create .

调整目录

将项目的目录调整到以下形式,该目录方式像是成了业界不成名的规定,element和iview都是以这样的方式组织的。我觉得挺好的,所以不做修改了。

image.png

其中:

|-- examples  // 为原来的src目录改名而来,用于测试编写的组件
|-- packages  // 用于组织我们的组件库

目录调整以后,我们需要修改相应的webpack配置,使原来的src目录指向修改后的examples目录,修改vue.config.js文件:

const path = require('path')
function resolve (dir) {
  return path.join(__dirname, '..', dir)
}

module.exports = {
    // 将entry指向examples
    pages: {
        index: {
            entry: 'examples/main.js',
            template: 'public/index.html',
            filename: 'index.html'
        }
    },
    // 为packages目录添加babel-loader处理
    chainWebpack: config => {
        config.module
        .rule('js')
        .include
            .add(resolve('packages'))
            .end()
        .use('babel')
            .loader('babel-loader')
            .tap(options => {
                return options
            })
    }
}

编写组件

packages目录下面的文件组织情况如下:

image.png

其中:

|-- datePicker      // 新编写的组件,以datepicker为例
|-- theme-default   // 主题文件

主题文件较为特殊,他作为单独的一个包进行发布引入,方便进行主题发布,后面再进行介绍。下面对datePicker进行介绍:

datePicker.vue

<template>
  <div>这是一个datePicker组件</div>
</template>

<script>
export default {
  name: 'datePicker'
}
</script>

datePicker/src/index.js

// 导入组件,组件必须声明 name
import datePicker from './src/datePicker.vue'

// 为组件提供 install 安装方法,供按需引入
datePicker.install = function (Vue) {
  Vue.component(datePicker.name, datePicker)
}

// 默认导出组件
export default datePicker
</script>

批量注册组件

// 导入日期选择器组件
import datePicker from './datePicker'

// 存储组件列表
const components = [
  datePicker
]

// 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册
const install = function (Vue) {
  // 判断是否安装
  if (install.installed) return
  // 遍历注册全局组件
  components.map(component => Vue.component(component.name, component))
}

// 判断是否是直接引入文件
if (typeof window !== 'undefined' && window.Vue) {
  install(window.Vue)
}

export default {
  // 导出的对象必须具有 install,才能被 Vue.use() 方法安装
  install,
  // 以下是具体的组件列表
  ...components
}

本地测试组件

我们的组件以及编写完成,第一步先在本地进行测试:
examples/main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'

// 导入组件库
import datePicker from './../packages/index'
import './../packages/theme-default/src/test.scss'

// 注册组件库
Vue.use(datePicker)

Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

examples/views/home.vue

<template>
  <div class="home">
    <datePicker></datePicker>
  </div>
</template>

<script>
export default {
  name: 'home'
}
</script>

如何在浏览器中就可以看到我们的组件运行成功了,下一步就是要将我们的代码打包成npm库了,那么需要通过vue-cli3中vue-cli-service的库模式进行打包。

库模式打包

# package.json
"script": {
    "build-lib": "vue-cli-service build --target lib --name frog-ui --dest lib packages/index.js  && npm run build-theme",
}

库模式的介绍:点击这里
执行:

npm run build-lib

项目的根目录新增了lib文件夹,内容如下


image.png

其中:

  • lib/frog-ui.common.js:一个给打包器用的 CommonJS 包
  • lib/frog-ui.umd.js:一个直接给浏览器或 AMD loader 使用的 UMD 包
  • lib/frog-ui.umd.min.js:压缩后的 UMD 构建版本

修改package.json

修改packages.json,目前我的项目的完整package.json如下:

{
  "name": "frog-ui",
  "version": "0.1.0",
  "private": false,
  "lisence": "MIT",
  "main": "lib/frog-ui.umd.min.js",
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "build-lib": "vue-cli-service build --target lib --name frog-ui --dest lib packages/index.js  && npm run build-theme",
    "build-theme": "gulp build --gulpfile packages/theme-default/gulpfile.js && cp-cli packages/theme-default/lib lib/theme-default",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^2.6.5",
    "vue": "^2.6.10",
    "vue-router": "^3.0.3"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^3.7.0",
    "@vue/cli-plugin-eslint": "^3.7.0",
    "@vue/cli-service": "^3.7.0",
    "@vue/eslint-config-standard": "^4.0.0",
    "babel-eslint": "^10.0.1",
    "cp-cli": "^2.0.0",
    "eslint": "^5.16.0",
    "eslint-plugin-vue": "^5.0.0",
    "gulp": "^4.0.2",
    "gulp-autoprefixer": "^6.1.0",
    "gulp-cssmin": "^0.2.0",
    "gulp-sass": "^4.0.2",
    "markdown-it-anchor": "^5.0.2",
    "markdown-it-container": "^2.0.0",
    "markdown-it-decorate": "^1.2.2",
    "markdown-it-task-checkbox": "^1.0.6",
    "node-sass": "^4.12.0",
    "sass-loader": "^7.1.0",
    "vue-markdown-loader": "^2.4.1",
    "vue-template-compiler": "^2.5.21"
  }
}

主要要修改的是:

{
  "private": false,      // 是否私有,必须指定为false才能发布到npm
  "main": "lib/frog-ui.umd.min.js",  // 编译后包的入口文件
}

根目录添加.npmignore文件

发布到npm下,只需要lib目录、package.json 和readme.md文件,所以需要忽略掉其他的目录
.npmignore

examples/
packages/
public/
vue.config.js
postcss.config.js
babel.config.js
*.map

发布npm

# 设置要发布的源,我发布的是通过verdaccio搭建的私库
npm config set registry http://registry.npmjs.org
# 登录
npm login
# 发布
npm publish

下图可以看到,我们的包发布成功了,关于私库的搭建可以查看我另外的文章。


image.png

总结

整个过程有一点点繁琐,但是能学到一些意外的知识,希望大家能够动手尝试。能力有限,文章中有写得不对的地方请大家见谅。如果对你有帮助的话,可以帮忙点个赞哦 ~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容

  • UI组件 element- 饿了么出品的Vue2的web UI工具套件 Vux- 基于Vue和WeUI的组件库 m...
    王喂马_阅读 6,441评论 1 77
  • UI组件 element- 饿了么出品的Vue2的web UI工具套件 Vux- 基于Vue和WeUI的组件库 m...
    小姜先森o0O阅读 9,395评论 0 72
  • UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基于Vue和WeUI的组...
    鲁大师666阅读 43,366评论 5 97
  • UI组件 element- 饿了么出品的Vue2的web UI工具套件 Vux- 基于Vue和WeUI的组件库 m...
    35eeabfa0772阅读 3,251评论 7 12
  • Vue2.0+组件库总结 UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基...
    szch阅读 1,958评论 1 52