zan-layer
v1.0.8
Published
A powerful layer component for Vue 3
Readme
zan-layer
Vue 3 弹层组件库,提供函数式弹层 API 和组件能力,适合中后台常见的消息、确认框、页面层、抽屉、通知、图片预览和输入层。
适用范围
- 通用确认框、消息、加载层
- 需要承载 Vue 组件内容的页面层 / 抽屉
- 图片预览、通知消息、输入弹层
- 希望用统一 API 管理打开、关闭、最大化、最小化、恢复等动作
安装
npm install zan-layer样式需要显式引入:
import 'zan-layer/lib/index.css'快速开始
全局安装
import { createApp } from 'vue'
import ZanLayer from 'zan-layer'
import 'zan-layer/lib/index.css'
const app = createApp(App)
app.use(ZanLayer)
app.mount('#app')安装后:
- 注册组件:
<ZanLayer /> - 挂载全局方法:
app.config.globalProperties.$layer - 可直接导入函数式 API:
import { layer, zanLayer } from 'zan-layer'
直接使用函数式 API
import { layer } from 'zan-layer'
layer.msg('操作成功')
layer.confirm('确定要删除吗?', {
yes: (id: string) => {
console.log('confirmed')
layer.close(id)
}
})导出内容
包对外提供:
- 默认导出:
ZanLayerPlugin - 命名导出:
layer - 命名导出:
zanLayer,与layer等价 - 命名导出:
ZanLayer - 类型导出:
LayerProps、BtnType、ImgListType等
常用方法
layer.open(options)
通用页面层入口,几乎所有复杂弹层场景都从这里开始。
const id = layer.open({
type: 'page',
title: '编辑商品',
content: '这里可以放字符串、VNode 或返回 VNode 的函数',
area: ['720px', '560px'],
shadeClose: false,
maxmin: true,
resize: true
})layer.msg(message, options?)
layer.msg('保存成功', {
icon: 1,
time: 2000
})layer.confirm(message, options?)
layer.confirm('确定提交吗?', {
yes: (id: string) => {
submit()
layer.close(id)
}
})layer.load(type?, options?)
const loadingId = layer.load(0, {
shade: true,
shadeOpacity: '0.3'
})
setTimeout(() => {
layer.close(loadingId)
}, 1500)layer.drawer(options)
layer.drawer({
title: '筛选条件',
content: '这里是抽屉内容',
offset: 'r',
area: ['420px', '100%']
})layer.notify(options)
layer.notify({
title: '新消息',
content: '订单已完成支付',
icon: 1,
offset: 'rt',
time: 3000
})layer.photos(options)
layer.photos({
imgList: [
{ src: '/img/1.jpg', alt: '图片1' },
{ src: '/img/2.jpg', alt: '图片2' }
],
startIndex: 0
})layer.prompt(options)
layer.prompt({
title: '请输入备注',
formType: 'textarea',
value: '默认内容',
maxLength: 100,
yes: (id: string, value: string) => {
console.log(value)
layer.close(id)
}
})LayerProps 核心字段
最常用字段如下:
| 字段 | 说明 |
| --- | --- |
| type | 弹层类型,支持数字和字符串别名 |
| title | 标题,可传字符串、VNode、返回 VNode 的函数,传 false 可隐藏 |
| footer | 底部区域内容 |
| content | 主体内容,支持字符串、VNode、函数 |
| area | 宽高,如 '560px' 或 ['720px', '560px'] |
| width | 单独指定宽度,会覆盖 area[0] |
| height | 单独指定高度,会覆盖 area[1] |
| minWidth | 最小宽度,支持数字或 CSS 尺寸字符串 |
| maxWidth | 最大宽度,支持数字或 CSS 尺寸字符串 |
| minHeight | 最小高度,支持数字或 CSS 尺寸字符串 |
| maxHeight | 最大高度,支持数字或 CSS 尺寸字符串 |
| offset | 位置,如 'r'、'rt'、'auto' 或坐标数组 |
| shade | 是否显示遮罩 |
| shadeClose | 点击遮罩是否关闭 |
| shadeOpacity | 遮罩透明度 |
| move | 是否允许拖拽 |
| resize | 是否允许右下角拉伸 |
| maxmin | 是否显示最大化/最小化按钮 |
| closeBtn | 是否显示关闭按钮 |
| btn | 自定义底部按钮 |
| btnAlign | 底部按钮对齐方式 |
| anim | 入场动画 |
| isOutAnim | 是否启用退场动画 |
| icon | 消息/通知图标 |
| time | 自动关闭时间,毫秒 |
| zIndex | 层级 |
| appContext | 函数式渲染时复用宿主 Vue app 上下文 |
弹层类型
type 支持数字和字符串两套写法:
0/'dialog'1/'page'2/'iframe'3/'loading'4/'drawer'5/'photos'6/'notify'7/'prompt'
在 Vue 组件中承载真实组件内容
这是中后台里最常见的用法。content 推荐直接传 VNode,且把 appContext 一起带上,避免丢失注入、全局组件或 UI 库上下文。
import { getCurrentInstance, h } from 'vue'
import { layer } from 'zan-layer'
import EditForm from './EditForm.vue'
const instance = getCurrentInstance()
layer.open({
type: 'page',
title: '编辑商品',
area: ['880px', '620px'],
resize: true,
maxmin: true,
appContext: instance?.appContext,
content: h(EditForm, {
productId: 1001
})
})如果你需要在关闭时拿到实例 ID,推荐先接住 open() 返回值:
const layerId = layer.open({
title: '详情',
appContext: instance?.appContext,
content: h(DetailPanel, {
onClose: () => layer.close(layerId)
})
})自定义按钮
layer.open({
title: '批量操作',
content: '确认执行吗?',
btnAlign: 'r',
btn: [
{
text: '取消',
callback: id => layer.close(id)
},
{
text: '确认',
type: 'primary',
callback: id => {
runAction()
layer.close(id)
}
}
]
})BtnType 支持:
texttypestyleclassdisabledcallback
生命周期和交互回调
常用业务回调
successendyesbeforeCloseclose
拖拽 / 缩放回调
moveStartmovingmoveEndresizeStartresizingresizeEnd
示例:
layer.open({
title: '可拖拽窗口',
content: '拖动后记录位置',
width: 720,
height: 520,
minWidth: 480,
minHeight: 320,
maxWidth: '90vw',
maxHeight: '90vh',
move: true,
resize: true,
moveEnd: (id, options) => {
console.log(id, options.left, options.top)
},
resizeEnd: (id, options) => {
console.log(id, options.width, options.height)
}
})控制方法
打开后可通过实例 ID 做控制:
layer.close(id)layer.closeAll()layer.reset(id)layer.min(id)layer.full(id)layer.revert(id)layer.resize(id, { width, height })
示例:
const layerId = layer.open({
title: '尺寸可控窗口',
content: '支持程序化改大小',
width: 640,
height: 420,
minWidth: 420,
minHeight: 260,
resize: true
})
layer.resize(layerId, {
width: '80vw',
height: '70vh'
})安装选项
插件安装时支持传入自定义 zIndex:
app.use(ZanLayer, {
zIndex: 3000
})使用建议
- 页面层、抽屉、复杂表单弹层优先走
layer.open()/layer.drawer() - 函数式打开 Vue 组件时,优先传
appContext - 通知和消息属于短生命周期,不要把复杂交互塞进
notify/msg - 如果你有统一视觉规范,建议在宿主项目里覆盖
layerClasses或contentClass
边界与限制
- 当前主打浏览器端函数式弹层,不是 SSR 优先组件
content是字符串时只做内容渲染,不会自动编译成 Vue 模板- 需要复杂表单、表格、图表内容时,推荐传真实 VNode,而不是大段 HTML 字符串
开发命令
npm run dev
npm run build
npm run acceptance:smoke