npm 发布 vue 日历组件包

之前写了一篇文章:NPM 包发包流程,大致介绍了如何通过 npm 发布一个自己的包;这一篇介绍一下如何发布一个自己的 vue 组件库到 npm 上;

一、背景

为什么要在 npm 上发布自己的 vue 组件库呢?
我们都知道在项目开发过程中,经常会遇到相似功能或者可以复用的模块;如果是在同一个项目中我们可以封装一个公用的组件来进行复用;
如果公司里面多个项目都有可以复用的模块呢?最简单的当然是直接复制一份到不同的项目中,但是这样在后期维护过程中,一个地方有变动你就需要在不同的项目中多次进行修改,这样就不怎么友好了;我们只要将组件上传到 npm 包管理工具上,在不同的项目中进行引入调用,如果有变动只需要更新 npm 上面的组件包就可以了;

二、准备工作

文本主要是基于 vue-cli3 构建的项目来封装组件;当然还有其他的方法,可以根据自己的喜好和能力选择;文章的后面还会简单介绍一下 vue init webpack-simple 构建的项目如何发包;
1、创建项目

vue create name

脚手架创建项目,这样很多配置虽然用不到,但是很方便;
2、新建文件夹:
在这里插入图片描述
如上图,新建 components 文件夹用来存放组件,组件文件夹内部新建 index.js 文件用来导出当前组件,在 src 同级新建 index.js 用来统一导出组件;

三、组件准备

本文以 calendar 组件为例,对比上面的目录:
1、src/components/calendar/index.vue

<template>
	<div>
		<div style="border-bottom: 1px solid #ccc; padding-bottom: 10px;">
	    	<el-select @change="skip('year')" v-model="Nyear" filterable placeholder="请选择">
		    	<el-option
		      v-for="item in year"
		      :key="item.value"
		      :label="item.label"
		      :value="item.value">
		    	</el-option>
		    </el-select>
		    <el-select @change="skip('month')" v-model="Nmonth" filterable placeholder="请选择">
		    	<el-option
		      v-for="item in month"
		      :key="item.value"
		      :label="item.label"
		      :value="item.value">
		    	</el-option>
		    </el-select>
	    </div>
	    <el-calendar v-model="value" ref="monChild">
	    	<template slot="dateCell" slot-scope="{date,data}">
	    		<div class="date-content">
	    			<!--周末不显示签到信息,并且置灰-->
	    			<p v-if="isWeekend(date)" style="display: flex; flex-direction: column; align-items: center;">
	    				<span style="color: #C0C4CC;" disabled>{{getDay(date)}}</span>
	    			</p>
			        <p v-else style="display: flex; flex-direction: column; align-items: center;">
			        	<span>{{ getDay(date) }}</span>
			        	<template v-if="needData(date,data)">
			        		<span v-if="arrInfo.indexOf(data.day) > -1" style="line-height: 30px; color: #ccc; display: flex; flex-direction: column; align-items: center;">
				        		已签
				        	</span>
				        	<span v-else style="color: red; line-height: 30px; ">未签</span>
			        	</template>
			        </p>
		      </div>
	    	</template>
	    </el-calendar>
	</div>
</template>
<script>
	export default {
	  name:"calendar",
	  data(){
			return{
				value:new Date(),
				arrInfo:['2022-02-01','2022-02-03'],
				Nyear:`${new Date().getFullYear()}`,
				Nmonth:`${new Date().getMonth() + 1}`,
				year:[{value:'2021',label:'2021年'},{value:'2022',label:'2022年'}],
				month:[
					{value:'1',label:'1月'},
					{value:'2',label:'2月'},
					{value:'3',label:'3月'},
					{value:'4',label:'4月'},
					{value:'5',label:'5月'},
				  {value:'6',label:'6月'},
				  {value:'7',label:'7月'},
				  {value:'8',label:'8月'},
				  {value:'9',label:'9月'},
				  {value:'10',label:'10月'},
				  {value:'11',label:'11月'},
				  {value:'12',label:'12月'}
				]
	    }
	  },
	  mounted(){
	  	 //去除组件原来的头部
		  this.$el.querySelector("div.el-calendar__header").remove();
	  },
	  methods:{
	  	//需要展示数据的日期
		needData(date,data){
			//只有展示月显示签到信息(如果是当前月,则只展示今天以前的签到信息)
			let curData = `${date.getFullYear()}-${date.getMonth()}` //展示的年月
			let newData = `${new Date().getFullYear()}-${new Date().getMonth()}` //当前年月
			if(data.type == 'current-month'){
				let curDay = date.getDate(); //日历当前项
				let newDay = new Date().getDate(); //今天
				if((curData == newData) && (curDay <= newDay)){
					return true
				}else if(curData != newData){
					return true
				}
			}else {
				return false
			}
		},
	  	//过滤周末
		isWeekend(date){
			if(date.getDay() == 0 || date.getDay() == 6){
				return true;
			}else {
				return false
			}
		},
	  	//选项框年月交互
	  	skip(type){
				if(type == 'year'){
					this.Nmonth = '1';
				}
				let value = new Date(`${this.Nyear}-${this.Nmonth}`);
				//同步更新日历
				this.value = new Date(value)
	  	},
	  	//获取当天时间默认显示
	  	getDay(date) {
	      return date.getDate()
	    }
	  }
	}
</script>
<style>
	/*禁止点击天跳转上一月、下一月*/
	.el-calendar-table:not(.is-range) td.next, .el-calendar-table:not(.is-range) td.prev {pointer-events: none;}
</style>

在这里插入图片描述
2、src/components/calendar/index.js,暴露单个组件,提供按需加载功能;

import calendar from './index.vue'
// 为组件提供 install 安装方法,供按需引入
calendar.install = function(Vue){
	Vue.component(calendar.name, calendar)
}
export default calendar

3、src/index.js,将组件导入,提供统一安装的 install 方法,并导出;

import calendar from './src/components/calendar'

let components = [calendar]
// 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,那么所有的组件都会被注册
let install = function(Vue){
	if(install.installed) return
	components.map(item => {
		Vue.component(item.name, item)
	})
}
// 判断是否是直接引入文件
if(typeof window !== 'undefined' && window.Vue){
	install(window.Vue)
}

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

4、本地调试
在 main.js 文件内部引入

import xxsui from '../index.js'
Vue.use(xxsui)

然后就可以在整个项目里使用所以的组件了,测试通过之后我们的组件就准备好了;

四、发包

1、src/package.json

  "name": "xxsui",
  "version": "1.0.0",
  "author": "xinsen.xiong <2575326615@qq.com>",
  "license": "MIT",
  "private": false,
  "main": "./lib/xxsui.umd.min",
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lib": "vue-cli-service build --target lib --name xxsui --dest lib index.js"
  },

将 private 设置为false,并添加 author、license、main、version、name、keywords 、description 等,同时需要修改打包后生产的文件,在 scripts 里面新增一个 lib 指令,目标 lib,指定打包后文件名 xxsui ,打包指向 index.js,最终生成文件在 lib 文件里:
在这里插入图片描述
我们要的是 xxsui.umd.min.js 这个文件,也是 main 指向的文件;
2、控制台执行命令打包项目

npm run lib 

3、npm 发包

npm login
npm publish

4、发包成功之后可以在 npm 官网查看是否存在组件包,以及版本时间
在这里插入图片描述
这样发包就结束了;

五、使用

新建一个项目,然后在项目中安装引入刚才发的包
安装:

npm i xxsui -s

引入:

inport xxsui from 'xxsui'
Vue.use(xxsui)

然后在项目中直接使用 xxsui 组件库中的组件,到这里整个依赖于 vue-cli3 搭建的组件库发包就完成了;

注意:如果 xxsui 组件库使用了其他组件库例如 elementui,在项目中使用 xxsui 的时候也需要将 elementui 安装引入;

六、webpack-simple 构建项目发包

这种方式发包和上面的基本上差不多,只是在 package.json 配置有所不同,然后多一个 webpack.config.js 的配置;
1、 package.json
将 private 设置为false,并添加 author、license、main、version、name、keywords 、description 等;其中 main 指向的是 webpack.config.js 中 output 中的 filename;

"name": "xxsui",
  "version": "1.0.0",
  "author": "xinsen.xiong <2575326615@qq.com>",
  "license": "MIT",
  "private": false,
  "main": "./dist/xxsui",
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
  },

这里自动生成的 scripts 不需要修改;
2、 webpack.config.js

 entry: './index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'xxsui.js' //指定生成文件名
  },

修改入口、出口,入口文件改为组件暴露的出口 index.js 文件;出口暴露出来的文件名修改为 js 文件;

最后

不管用什么方法创建的项目,最终都是要把文件打包成一个 js 文件;区别就是 vue-cli3 内部已经做了大量的处理,只需要修改 package.json 里面的打包配置就可以了,而 webpack-simple 需要自己配置打包文件的入口、出口;

如有错误或者遗漏,欢迎留言指正!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值