引言
作者为了找款好用的瀑布流组件,看了很多的开源库,发现都不是特别满意,我需要的是一个支持动态列数和虚拟列表的,所以打算自己撸一个。
不想看废话的可以拉到底部看源码
环境和框架版本
- vue:
3.3.4
- vite:
4.4.7
- typescript:
5.1.6
- pnpm:
8.6.10
- node:
20.5.0
预览
开发
只列出部分,想查看全部源码,可以拉至最底部
├── src
│ └── vue-virtual-waterfall // 组件源码,单独放一个文件夹内
│ ├── index.ts // 组件导出
│ └── virtual-waterfall.vue // 实现,按正常实现组件就行了,没特别说明
index.ts
组件导出特别提一下
import type { App } from 'vue'
import VirtualWaterfall from './virtual-waterfall.vue'
// 这里导出单个,可以单独引用
export { VirtualWaterfall }
// 这里导出一个默认对象,包含一个install方法,支持全局导入
export default {
install(app: App) {
app.component(VirtualWaterfall.name, VirtualWaterfall)
}
}
// 在这里进行全局声明,不然全局安装时没有提示
declare module 'vue' {
export interface GlobalComponents {
VirtualWaterfall: typeof VirtualWaterfall
}
}
- 下面是vite的打包配置
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 如果是jsx写的组件需要引入这个,我用的template所以不用
// import vueJsx from '@vitejs/plugin-vue-jsx'
// 生成ts的声明文件,方便提示
import dts from 'vite-plugin-dts'
// 这个是把css写入到js里就不用单独引入样式文件了
// 如果样式比较少可以用这种方式,多的话就单独引入样式文件吧
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
let base = '/'
let plugins = [
vue()
]
let build: Record<string, any> = {
target: 'es2015',
cssTarget: 'chrome61'
}
// vite build时可以传 `--mode npm`
// 只有mode等于npm时才打包组件,否则的就可以预览组件了
if (mode === 'npm') {
plugins = [
vue(),
cssInjectedByJsPlugin(),
dts({
// 我们只需要组件这里生成声明文件,所以要指明位置
entryRoot: 'src/vue-virtual-waterfall'
})
]
build = {
// 兼容js
target: 'es2015',
// 兼容css
cssTarget: 'chrome61',
// 我们组件不需要public里的玩意
copyPublicDir: false,
lib: {
// 这是入口文件
entry: 'src/vue-virtual-waterfall/index.ts',
// 最终生成的js格式,这里写三种常见的
formats: ['cjs', 'es', 'umd'],
// 全局引入时的名字
name: 'VueVirtualWaterfall',
// build后的文件名
fileName: 'index'
},
// 我们不需要把vue里的东西打包进来,这里将其排除在外
rollupOptions: {
external: ['vue'],
output: {
globals: {
vue: 'Vue'
},
exports: 'named'
}
}
}
}
return {
base,
plugins,
build
}
})
发布
当然是使用github action
进行发布,我希望提交后,自动识别package.json
里的version
属性发布版本,所以将要完成下面三步:
- 需要写个github的ci脚本(支持创建release)
- 写个提取version的脚本
- 发布到npm,这步的代码也放在2
- 前置,发布到npm,
package.json
也要配置好,下面列几个关键的属性
{
"name": "组件的名字",
"version": "版本号",
"license": "MIT",
"type": "module",
"scripts": {
"build:npm": "vue-tsc && vite build --mode npm",
"pub": "bash scripts/publish.sh"
},
"main": "dist/index.cjs",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"keywords": [
"vue3",
"waterfall",
"virtual-list"
],
"files": [
"dist",
"README.md",
"LICENSE",
"package.json"
]
}
- 先写
github action
的脚本
name: Publish Package
on:
push:
branches:
- main
jobs:
publish:
runs-on: ubuntu-latest
environment: Release
steps:
# 把代码拷贝下来
- name: Checkout
uses: actions/checkout@v3
# 我们使用的是pnpm
- name: Install pnpm
uses: pnpm/action-setup@v2
with:
version: 8
# 安装依赖
- name: Install deps
run: pnpm i --no-frozen-lockfile --shamefully-hoist
# 使用的node
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18
registry-url: 'https://registry.npmjs.org/'
cache: 'pnpm'
# 打包
- name: Build
# 这里执行的是package.json里的一个命令,可以找下上面的
run: pnpm build:npm
# 这里也是调用package.json的命令,用于发布到npm
- name: publish
run: pnpm pub
env:
# 这里要设置npm的token
NODE_AUTH_TOKEN: '${{secrets.NPM_AUTH_TOKEN}}'
# 上面执行成功表示发布到了npm,然后我们要在github仓库里创建一个release
# 这里的命令是为了把package.json里的version版本号提取出来,放在GITHUB_ENV里,供下面的使用
- run: |
echo "version=$(grep -o '"version": *"[^"]*"' package.json | awk -F'"' '{print $4}')" >> "$GITHUB_ENV"
# 这里打印了一下提取的版本号,看下对不对
- run: |
echo "version: ${{ env.version }}"
# 仓库创建一个release
- uses: ncipollo/release-action@v1
with:
# 这里使用的版本号就是上面的提取的,可以按自己喜欢命名,我这里前面加了一个v
tag: "v${{ env.version }}"
# 我为了确认是否要发布release设置成草稿,ok我就发布release
draft: true
token: ${{ secrets.TOKEN }}
- 发布到npm的脚本
上面有个pnpm pub
,这是调用的是bash scripts/publish.sh
脚本,我这里用的是shell,比较熟悉,也可以琢磨一下python、js
#!/bin/bash
# 发布版本
function pub(){
# 获取项目package.json文件
path="./package.json"
# 获取项目版本号
version=$(awk '/version/{gsub(/("|",)/,"",$2);print $2};' $path)
if [ -z "$version" ]; then
exit 1
fi
# 获取tag,npm支持多种tag,如果不指定,则会发布到latest
# 我这里会根据版本号提取出tag,如
# 0.0.1-beta 提取出beta
# 0.1.1-next.0 提取出next
# 1.0.0-alpha.11 提取出alpha
# 2.0.0 提取出latest
tag=${version#*-}
tag=${tag%.*}
case $tag in
"alpha") tag="alpha"
;;
"beta") tag="beta"
;;
"next") tag="next"
;;
*) tag="latest"
;;
esac
# 这里打印一下提取出的版本号和tag,如: 1.0.0 beta
echo $version, $tag
# 发布
pnpm publish --no-git-checks --tag $tag --access=public
}
# 这里是调用上面的函数
pub
到此就发布好了
使用
不想写了,自己看源码吧