# 前言
这几天掘金社区 (opens new window)好文章很多,有点眼花缭乱,各种点赞收藏,收藏了就是会了。
简单的记录一下从零到成功发布npm组件包,为什么选择拖拽组件,也许是最近点赞和收藏了阿宝哥 (opens new window)的拖拽竟然还能这样玩! (opens new window)
回归本文:下面开始演示我从零创建项目,到发布该项目,并附上代码
# Vite 快速构建 Vue 新项目
首先使用vite-app去搭建一个最简单的轻型项目
# 使用npm
$ npm init vite-app <project-name>
$ cd <project-name>
$ npm install
$ npm run dev
1
2
3
4
2
3
4
# 或使用yarn
$ yarn create vite-app <project-name>
$ cd <project-name>
$ yarn
$ yarn dev
1
2
3
4
2
3
4
# 成功安装依赖并运行
项目构建好,安装依赖并运行,如下:
# 写个组件
这步是写一个你想发布的组件。
# 项目演示
# 项目目录介绍
├── src
│ ├── assets # 本地静态资源(一个vue的logo,可以删除)
│ ├── components # 业务通用组件
│ │ ├── VueXiaoerDragEle.vue # 本文需要封装的拖拽组件
│ │ ├── VueXiaoerDragEle.css # 本文需要封装的拖拽组件的样式
│ ├── utils # 工具库(封装的工具,比如添加事件函数和删除事件函数,和一些计算高宽的函数)
│ └── index.css # 主页样式
| └── APP.vue # 主页
| └── main.js # 应用入口
├── .npmignore // 用于忽略不需要上传到npm的文件
├── README.md
└── package.json # 项目配置
// 注意
# utils 文件夹一般存放的是你组件经常使用的一些工具函数
# assets 文件夹一般存放的是你组件用到的样式、图片、icon等静态资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 组件中鼠标按下处理函数
handleDown (handle, e) {
if (e instanceof MouseEvent && e.which !== 1) {
return
}
if (this.onResizeStart(handle, e) === false) {
return
}
if (e.stopPropagation) e.stopPropagation()
// Here we avoid a dangerous recursion by faking
// corner handles as middle handles
if (this.lockAspectRatio && !handle.includes('m')) {
this.handle = 'm' + handle.substring(1)
} else {
this.handle = handle
}
this.resizing = true
this.mouseClickPosition.mouseX = e.touches ? e.touches[0].pageX : e.pageX
this.mouseClickPosition.mouseY = e.touches ? e.touches[0].pageY : e.pageY
this.mouseClickPosition.left = this.left
this.mouseClickPosition.right = this.right
this.mouseClickPosition.top = this.top
this.mouseClickPosition.bottom = this.bottom
this.mouseClickPosition.w = this.width
this.mouseClickPosition.h = this.height
this.bounds = this.calcResizeLimits()
addEvent(document.documentElement, eventsFor.move, this.handleResize)
addEvent(document.documentElement, eventsFor.stop, this.handleUp)
},
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
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
# 组件中鼠标松开处理函数
async handleUp (e) {
this.handle = null
// 初始化辅助线数据
const temArr = new Array(3).fill({ display: false, position: '', origin: '', lineLength: '' })
const refLine = { vLine: [], hLine: [] }
for (let i in refLine) { refLine[i] = JSON.parse(JSON.stringify(temArr)) }
if (this.resizing) {
this.resizing = false
await this.conflictCheck()
this.$emit('refLineParams', refLine)
this.$emit('resizestop', this.left, this.top, this.width, this.height)
}
if (this.dragging) {
this.dragging = false
await this.conflictCheck()
this.$emit('refLineParams', refLine)
this.$emit('dragstop', this.left, this.top)
}
this.resetBoundsAndMouseState()
removeEvent(document.documentElement, eventsFor.move, this.handleResize)
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 组件中移动的实现:
// 元素移动
async handleDrag (e) {
const axis = this.axis
const grid = this.grid
const bounds = this.bounds
const mouseClickPosition = this.mouseClickPosition
const tmpDeltaX = axis && axis !== 'y' ? mouseClickPosition.mouseX - (e.touches ? e.touches[0].pageX : e.pageX) : 0
const tmpDeltaY = axis && axis !== 'x' ? mouseClickPosition.mouseY - (e.touches ? e.touches[0].pageY : e.pageY) : 0
const [deltaX, deltaY] = snapToGrid(grid, tmpDeltaX, tmpDeltaY, this.scaleRatio)
const left = restrictToBounds(mouseClickPosition.left - deltaX, bounds.minLeft, bounds.maxLeft)
const top = restrictToBounds(mouseClickPosition.top - deltaY, bounds.minTop, bounds.maxTop)
if (this.onDrag(left, top) === false) {
return
}
const right = restrictToBounds(mouseClickPosition.right + deltaX, bounds.minRight, bounds.maxRight)
const bottom = restrictToBounds(mouseClickPosition.bottom + deltaY, bounds.minBottom, bounds.maxBottom)
this.left = left
this.top = top
this.right = right
this.bottom = bottom
await this.snapCheck()
this.$emit('dragging', this.left, this.top)
},
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
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
# 发包前配置
npm发布前两步走,1.暴露组件;二:打包配置
# 1.暴露组件
新建个index.js,然后里面写上导出之前的组件
import './components/VueXiaoerDragEle.css'
import VueXiaoerDragEle from './components/VueXiaoerDragEle'
export function install(Vue) {
if (install.installed) return
install.installed = true
Vue.component('VueXiaoerDragEle', VueXiaoerDragEle)
}
const plugin = {
install
}
let GlobalVue = null
if (typeof window !== 'undefined') {
GlobalVue = window.Vue
} else if (typeof global !== 'undefined') {
GlobalVue = global.Vue
}
if (GlobalVue) {
GlobalVue.use(plugin)
}
export default VueXiaoerDragEle
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
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
# 二.使用vue-cli的vue-cli-service build打包命令
这里也可以选择rollup去配置打包(这里省略了) 安装vue-cli后,加上打包配置,打包入口指向上一步的index.js
"build": "vue-cli-service build --target lib --name VueXiaoerDragEle ./src/index.js"
1
到这,发包前配置就完成了,下面开始说发布的步骤
# npm发布
# 注册账号(已有跳过)
需要npm账号,没有的话去官网 (opens new window)注册一个,等等发包需要账号登录的
# 镜像源
发包需要使用官网的镜像源,如果是淘宝等其他镜像源,需要改成官网的镜像源:
npm config set registry http://registry.npmjs.org
1
# 登录
npm login
1
依次输入用户名,密码,邮箱
成功的话有提示,然后下一步
# 发布
发包就一个简单的命令:
npm publish
1
成功发布如下:
# 验证
我们刚刚成功发布了vue-xiaoer-drag-ele组件,
# 查看组件npm官网的仓库
这是npm官网 (opens new window)用你刚刚使用的账号登录的仓库(profile)管理,可以看见你的包列表。比如我这个账号发了两个包,时间、包名等等:
# 使用该依赖包
在别的项目中安装该依赖包 然后导入使用;
到这,就完成了从零到发包了。
PS: 换回国内镜像
npm config set registry https://registry.npm.taobao.org
1
# 总结:
键盘在手,跟我走,轻轻松松发布一个属于你自己的组件。
!十分感谢你认真的看完
不妨点个赞,鼓励一下楼主,谢谢!