自定义Vite库并发布到NPM

封装useResize

用于监听绑定元素的宽高变化,当元素宽高发生变化时触发回调并获取最新的宽高

新建项目

结合上面学到的 Hook 和 自定义指令封装一个监听元素宽高变化的指令,并发布到 npm

项目结构

1
2
3
4
5
6
7
8
9
useResize            
├── src
│ └── index.ts
├── README.md
├── index.d.ts
├── package-lock.json
├── package.json
├── tsconfig.json
└── vite.config.ts

src/index.ts

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
35
36
37
38
import type {App} from "vue";

/**
* 自定义Hook
* @param el
* @param callback
*/
const weakMap = new WeakMap<HTMLElement, Function>();
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
const handle = weakMap.get(entry.target as HTMLElement);
handle && handle(entry)
}
})

function useResize(el: HTMLElement, callback: Function) {
if (weakMap.get(el)) {
return
}
weakMap.set(el, callback)
resizeObserver.observe(el)
}

/**
* 定义vite插件时,vue会在底层调用插件的install方法
* @param app
*/
function install(app: App) {
app.directive('resize', {
mounted(el: HTMLElement, binding: { value: Function }) {
useResize(el, binding.value)
}
})
}

useResize.install = install

export default useResize

vite.config.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import {defineConfig} from "vite"

export default defineConfig({
build:{
lib:{
// 打包入口文件
entry:"src/index.ts",
// name
name:"useResize"
},
rollupOptions:{
// 忽略打包的文件
external:['vue'],
output:{
globals:{
useResize:"useResize"
}
}
}
}
})

index.d.ts

1
2
3
4
5
6
declare const useResize:{
(element:HTMLElement, callback:Function):void
install:(app:any) => void
}

export default useResize

package.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"name": "v-resize-songzx",
"version": "1.0.0",
"description": "",
"main": "dist/v-resize-songzx.umd.js",
"module": "dist/v-resize-songzx.mjs",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "vite build"
},
"keywords": [],
"author": "songzx",
"files": [
"dist",
"index.d.ts"
],
"license": "ISC",
"devDependencies": {
"vue": "^3.3.4"
},
"dependencies": {
"vite": "^4.4.9"
}
}

pachage.json 文件属性说明:

  • name:对应打包后生成的包名,也就是上传到npm上面的包名,不能包含数字和特殊符号
  • version:包的版本号
  • main:对应打包后的 umd.js 文件,在使用 app.use 时会访问使用文件
  • module:使用import、require等方式引入时会使用 mjs 文件
  • files:指定那些文件需要上传

打包

1
npm run build

登录npm

1
npm login

image-20230924231941434

发布

1
npm publish

image-20230924232715692

打开 npm 网站,搜索查看是否发布成功

image-20230925090849623

使用自己的库

安装

1
npm i v-resize-songzx

使用方式一

全局注册 v-resze 指令

main.ts 引入

1
2
3
4
5
6
import useResize from "v-resize-songzx";

const app = createApp(App)

app.use(useResize)
app.mount('#app')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div class="resize" v-resize="getNewWH"></div>
</template>

<script setup lang="ts">
const getNewWH = (e) => {
console.log(e.contentRect.width, e.contentRect.height);
}

</script>

<style scoped>
/*把一个元素设置成可以改变宽高的样子*/
.resize {
resize: both;
width: 200px;
height: 200px;
border: 1px solid;
overflow: hidden;
}
</style>

使用方式二

使用Hook的方式

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
<template>
<div class="resize"></div>
</template>

<script setup lang="ts">

import useResize from "v-resize-songzx";

onMounted(() => {
useResize(document.querySelector(".resize"), e => {
console.log(e.contentRect.width, e.contentRect.height);
})
})

</script>

<style scoped>
/*把一个元素设置成可以改变宽高的样子*/
.resize {
resize: both;
width: 200px;
height: 200px;
border: 1px solid;
overflow: hidden;
}
</style>