基于Vue-cli4.x二次封装Element-ui组件并发布到npm
转载自:www.yuque.com/homacheuk/d…
其他: blog.csdn.net/shidouyu/ar…
https://juejin.cn/post/6844904000655998984#heading-19
https://juejin.cn/post/6844903926941089806#heading-29
需求
由于需要重新做一套基于el组件的公用组件,并且提供给多个子系统使用,因此这次选择将组件封装并发布到npm上。
正文
封装组件库的方式有很多,但我们从简单入手,直接使用vue-cli来创建,虽然有点冗余但是胜在方便调试组件。
安装vue-cli4并创建一个组件库项目
//安装脚手架
yarn global add @vue/cli
// 创建项目
vue create jz-vue-ui
- 创建完成项目后(对创建流程不熟的小伙伴可以自行百度)我们就有了以下的项目目录。包含了基本项目需要的vuex、router等,这个因为我项目后期需要所以就增加了,可以看个人需要来确定是不是加上。
调整为
目录的结构我们参考下element的项目结构,需要将src重命名为examples, 并添加packages目录,用来存放我们的自定义组件.
但是cli默认会启动src下的服务,如果目录名变了,我们需要手动修改配置,vue-cli3中提供自定义打包配置项目的文件,我们只需要手动创建vue.config.js即可.我们具体修改如下:
1.首先修改入口文件地址为examples下的main.js,
2.其次将packages加入打包编译任务中
3.将@等路径昵称修改掉
const path = require('path') // 引入path模块
function resolve (dir) {
return path.join(__dirname, dir) // path.join(__dirname)设置绝对路径
}
module.exports = {
publicPath: './',
// 1.更改入口和出口文件名
pages: {
index: {
entry: 'examples/main.js',//修改入口
template: 'public/index.html',
filename: 'index.html'
}
},
// 2.扩展 webpack 配置,使 packages 加入编译
chainWebpack: config => {
config.resolve.alias
.set('@', resolve('./examples')) //3.修改快捷路径
.set('components', resolve('./examples/components'))
.set('views', resolve('./examples/views'))
.set('assets', resolve('./examples/assets'))
config.module
.rule('js')
.include
.add('/packages/')
.end()
.use('babel')
.loader('babel - loader')
.tap(options => {
// 修改它的选项...
return options
})
},
/* 输出文件目录:在npm run build时,生成文件的目录名称 */
outputDir: 'jz-vue-ui',
/* 放置生成的静态资源 (mixin、css、img、fonts) 的 (相对于 outputDir 的) 目录 */
assetsDir: 'assets',
/* 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度 */
productionSourceMap: false,
/* 默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存,你可以通过将这个选项设为 false 来关闭文件名哈希。(false的时候就是让原来的文件名不改变) */
filenameHashing: false,
/* 代码保存时进行eslint检测 */
lintOnSave: false,
/* webpack-dev-server 相关配置 */
devServer: {
/* 自动打开浏览器 */
open: true,
/* 设置为0.0.0.0则所有的地址均能访问 */
host: '192.168.0.142',
port: 8080,
https: false,
hotOnly: false
}
}
编写基于el的组件
- 由于我们需要基于el来封装组件,因此我们先装下element-ui,按照网上说的直接在vue ui 上点击装也可以,这里我们使用传统的方式
yarn add element-ui -S
然后编写组件的时候直接使用按需引入会相对节省空间,因此我们按照官网的说法引入
yarn add babel-plugin-component -D
并在babel.config.js中添加
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk'
}
]
]
}
-
下面我们拿一个Button组件来示范,这里只实现一个比较简单的组件。
首先我们先在packages目录下新建一个Button目录,然后src里存放组件的源代码
<template>
<div>
<p>测试q</p>
<Button>el-button</Button>
</div>
</template>
<script>
import { Button } from 'element-ui'//按需引入
export default {
name: 'jz-button',
components: { Button }
}
</script>
Button的index.js里编写如下代码来作为vue的组件安装:
import Button from './src/index.vue'
Button.install = function (Vue) {
Vue.component(Button.name, Button)
}
export default Button
接下来我们在packages的入口文件中导入组件并安装导出)
这里需要注意,因为由于el有样式的css,且我们用的按需引入,因此要在这里去引入下
import 'element-ui/lib/theme-chalk/index.css'//引入el的样式
import Button from './Button/index'
import Input from './Input/index'
// 存储组件列表
const components = [Button]
// 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册
const install = function (Vue) {
// 判断是否安装
if (install.installed) return
// 遍历注册全局组件
components.forEach(component => {
Vue.component('jz-button', component)
})
}
// 判断是否是直接引入文件
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export default {//引入全部
// 导出的对象必须具有 install,才能被 Vue.use() 方法安装
install
}
export {//局部引入
Button,
Input
}
测试代码
我们要想看到自己写的组件效果,可以将组件导入到examples目录下的main.js中,其本质就是一个项目的开发目录,我们只需要按照如下方式导入即可:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import jzUI from '../packages/index'
Vue.config.productionTip = false
Vue.use(jzUI) // 这里我们为了方便直接引入全部
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
接下来我们就可以在项目中使用我们的组件了
<template>
<div id="app">
<jz-button></jz-button>
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view/>
</div>
</template>
<style lang="scss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
</style>
配置package.json文件
作为一个组件库,我们必须按照npm的发包规则来编写我们的package.json, 正常情况下我们需要配置
package文件的description,keywords等,具体介绍如下:
-
description 组件库的描述文本
-
keywords 组件库的关键词
-
license 许可协议
-
repository 组件库关联的git仓库地址
-
homepage 组件库展示的首页地址
-
main 组件库的主入口地址(在使用组件时引入的地址)
-
private 声明组件库的私有性,如果要发布到npm公网上,需删除该属性或者设置为false
-
publishConfig 用来设置npm发布的地址,这个配置作为团队内部的npm服务器来说非常关键,可以设置为私有的npm仓库
注意:由于我们使用的是不打包的模式,直接main入口路径修改为修改为jz-vue-ui/package,调用时的引入路径可以简化调用
//我们先使用最基础的这几个属性即可
"name": "jz-vue-ui",
"version": "0.1.9",
"private": false,
"description": "jz前端公用组件库",
"main": "jz-vue-ui/package",
其次是需要配置打包的命令,这个我们也先给他配上,虽然我们本次并不使用他
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",json
"lint": "vue-cli-service lint",
//包名 及打包入口
"lib": "vue-cli-service build --target lib --name jz-vue-ui --dest lib packages/index.js"
},
最后我们需要创建一个.npmignore忽略掉一些不需要上传的文件减少大小
# 忽略目录
examples/
#packages/
#public/
# 忽略指定文件
vue.config.js
babel.config.js
*.map
发布到npm
- 这次我们使用非打包发布,因为我们组件库可能还会用到很多第三方库及资源,使用这种方式可以避免资源加载错误
打包发布和非打包发布对比如下:
- 发布到npm的方法也很简单, 首先我们需要先注册去npm官网注册一个账号(记住要验证邮箱), 然后控制台登录即可,最后我们执行npm publish即可.具体流程如下
// 登录,并按提示输入账号密码
npm login
// 发布 每次发布需要提高版本号
npm publish
发布之后效果如下:
在项目中使用
- 现在我们创建一个新的vue项目并引入我们的组件库
//安装组件库
yarn add jz-vue-ui
- 由于在配置main将引入路径修改为:jz-vue-ui/package,因此这里的引入可以直接使用jz-vue-ui
在main.js中引入
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { Input } from 'jz-vue-ui'
import './css/index.scss' // 覆盖css需要放在后面
Vue.config.productionTip = false
Vue.use(Input)
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
- 这里我们会注意到一个问题,引入的路径并不止我们的组件库名,这是因为我们是没打包直接发布,因此需要手动去找到库的入口js,实际上安装完成后的组件库在node_modules中是这样的:
- 接下来我们来使用它,其实使用方法和调试的时候差不多
<template>
<div id="app">
<jz-input></jz-input>
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view/>
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
</style>
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!