设计

需求:实现一个函数,同时支持hook和自定义指令,去监听DOM宽高的变化

攻克点:

  1. 如何监听DOM宽高变化
  2. 如何用vite打包库
  3. 如何发布npm

编码

创建一个基本的工程,作为开发依赖引入vue3和vite后,编写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
import type { App } from "vue"

// MutationObserver 主要侦听子集、属性、增删改查的变化
// ResizeObserver 主要侦听元素宽高的变化
// 实现自定义hook
function useResize(el: HTMLElement, callback: Function) {
let resize = new ResizeObserver((entries)=> {
// 用回调函数回传元素宽高
callback(entries[0].contentRect)
})
resize.observe(el)
}

// Vue插件的规范(实现install函数)
const install = (app:App)=> {
// 实现自定义指令
app.directive("resize", {
mounted(el,binding) {
useResize(el,binding.value)
}
})
}

// 把install方法加到useResize身上
useResize.install = install

export default useResize

编写声明文件index.d.ts:

1
2
3
4
5
6
7
8
9
import { App } from "vue"

// 编写声明文件
declare const useResize: {
(el:HTMLElement,callback:Function):void
install:(app:App)=>void
}

export default useResize

打包成库

配置vite.config.js:

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
import { defineConfig } from "vite"

// umd 支持amd、cmd、cjs和全局变量模式
export default defineConfig({
build: {
// 开发面向浏览器的库时使用
lib: {
// 入口文件
entry: "src/index.ts",
// 包名
name: "useResize"
},
// 透传属性
rollupOptions: {
// 排除vue(不想被打包进库的依赖)
external: ["vue"],
output:{
globals:{
// 给umd全局变量用
useResize:"useResize"
}
}
}
}
})

使用vite build将包打出来,会在dist文件夹打出两个文件,.mjs是ES Module模式,.umd.js是各种模式的综合。

发布到NPM

修改package.json:

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

然后通过三步把包发到npm上:

  1. 需要拥有npm账号,没有的话使用npm adduser命令注册
  2. 登录npm,使用npm login
  3. 使用npm publish发布