vue-modal-core
Advanced tools
Comparing version
import * as vue from 'vue'; | ||
import { Component, InjectionKey, VNodeProps, AllowedComponentProps } from 'vue'; | ||
import { Component, VNodeProps, AllowedComponentProps, InjectionKey } from 'vue'; | ||
@@ -45,2 +45,3 @@ /** | ||
declare const ModalKey: InjectionKey<ModalContext>; | ||
declare const ModalIdKey: InjectionKey<symbol>; | ||
/** | ||
@@ -60,3 +61,3 @@ * 模态框配置选项接口 | ||
* @param fn 钩子函数,返回 false 可以阻止模态框关闭 | ||
* @throws 如果在组件外部使用或未找到模态框上下文会抛出错误 | ||
* @throws 如果在组件外部使用或未找到模态框上下文会打印警告 | ||
*/ | ||
@@ -71,3 +72,3 @@ declare const onBeforeClose: (fn: () => Promise<void | boolean> | void | boolean) => void; | ||
makeModal: <C extends Component<{ | ||
visible?: boolean; | ||
visible?: boolean | undefined; | ||
}>>(comp: C, id?: symbol) => { | ||
@@ -101,2 +102,2 @@ id: symbol; | ||
export { type ExtractComponentOptions, type ModalContext, ModalKey, type ModalMeta, type ModalOptions, createModalContext, onBeforeClose }; | ||
export { type ExtractComponentOptions, type ModalContext, ModalIdKey, ModalKey, type ModalMeta, type ModalOptions, createModalContext, onBeforeClose }; |
// src/core.ts | ||
import { shallowReactive, getCurrentInstance, provide, inject, h, onUnmounted } from "vue"; | ||
var ModalKey = Symbol("modal-context"); | ||
var ModalIdKey = Symbol("modal-id"); | ||
var DEFAULT_OPTIONS = { | ||
@@ -12,16 +13,19 @@ baseZIndex: 1e3, | ||
if (!ctx) { | ||
throw new Error("onBeforeClose must be used in a component"); | ||
console.warn("onBeforeClose must be used in a component"); | ||
return; | ||
} | ||
const modalContext = inject(ModalKey); | ||
if (!modalContext) { | ||
throw new Error("Modal context not found, make sure ModalRenderer is mounted"); | ||
console.warn("Modal context not found, make sure ModalRenderer is mounted"); | ||
return; | ||
} | ||
const modalId = ctx.vnode.key; | ||
const modalId = inject(ModalIdKey); | ||
if (!modalId) { | ||
throw new Error("Component must have a key"); | ||
console.warn("ModalId not found, make sure the component is used inside a modal"); | ||
return; | ||
} | ||
const componentId = Symbol("ComponentId"); | ||
modalContext.addClosePromise(modalId, componentId, fn); | ||
const fnId = Symbol("fnKey"); | ||
modalContext.addClosePromise(modalId, fnId, fn); | ||
onUnmounted(() => { | ||
modalContext.removeComponentPromises(modalId, componentId); | ||
modalContext.removeComponentPromises(modalId, fnId); | ||
}); | ||
@@ -58,5 +62,5 @@ }; | ||
const modal = modalsMap.get(id); | ||
if (!modal || modal.meta.isClosing) return false; | ||
if (!modal || modal.meta.isClosing) | ||
return false; | ||
modal.meta.isClosing = true; | ||
modal.props.visible = false; | ||
log("Closing modal", id); | ||
@@ -77,3 +81,2 @@ try { | ||
modal.meta.isClosing = false; | ||
modal.props.visible = true; | ||
return false; | ||
@@ -121,3 +124,9 @@ } | ||
modalsMap.set(id, { | ||
comp, | ||
comp: { | ||
...comp, | ||
setup: (props2, context) => { | ||
provide(ModalIdKey, id); | ||
return typeof comp === "object" && comp.setup ? comp.setup(props2, context) : void 0; | ||
} | ||
}, | ||
props: shallowReactive({ | ||
@@ -182,2 +191,3 @@ ...props, | ||
export { | ||
ModalIdKey, | ||
ModalKey, | ||
@@ -184,0 +194,0 @@ createModalContext, |
{ | ||
"name": "vue-modal-core", | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"license": "MIT", | ||
@@ -5,0 +5,0 @@ "description": "一个轻量级的 Vue 3 模态框管理库,提供灵活的模态框控制和生命周期管理", |
167
README.md
@@ -1,4 +0,4 @@ | ||
# Vue Modal Core | ||
# vue-modal-core | ||
一个轻量级的 Vue 3 模态框管理库,提供灵活的模态框控制和生命周期管理。 | ||
一个轻量级且灵活的 Vue 3 模态框组件库,为您的 Vue 应用提供更好的模态框管理方案。 | ||
@@ -10,8 +10,8 @@ [](https://www.npmjs.com/package/vue-modal-core) | ||
- 🎯 TypeScript 支持 | ||
- 🔄 响应式状态管理 | ||
- 🎨 灵活的模态框组件复用 | ||
- 🔒 完整的生命周期控制 | ||
- ⚡ 支持异步关闭控制 | ||
- 🎯 完全基于 TypeScript 开发,提供完整的类型支持 | ||
- 🚀 轻量级设计,无外部依赖 | ||
- 💪 支持异步关闭控制 | ||
- 🎨 灵活的自定义样式 | ||
- 📦 支持多模态框管理 | ||
- 🔧 简单易用的 API | ||
@@ -28,11 +28,38 @@ ## 安装 | ||
## 基础用法 | ||
## 快速开始 | ||
1. 首先创建你的模态框组件(例如 `MyModal.vue`): | ||
1.创建实例 | ||
```typescript | ||
// dialog.ts | ||
import { createModalContext } from 'vue-modal-core'; | ||
export { makeModal, ModalRenderer } = createModalContext({ | ||
baseZIndex: 1000, | ||
allowMultiple: true | ||
}); | ||
``` | ||
2. 创建模态框组件: | ||
```vue | ||
<!-- MyModal.vue --> | ||
<script setup lang="ts"> | ||
import { onBeforeClose } from 'vue-modal-core'; | ||
defineProps<{ | ||
content: string; | ||
}>() | ||
defineModel<boolean>('visible') | ||
// 在模态框组件中使用关闭前钩子 | ||
onBeforeClose(async () => { | ||
await new Promise(resolve => setTimeout(resolve, 1000));// 等待 1 秒 | ||
// 返回 false 可以阻止模态框关闭 | ||
}); | ||
</script> | ||
<template> | ||
<div v-if="visible" class="modal"> | ||
<div class="modal" :class="{ 'show': visible }"> | ||
<div class="modal-content"> | ||
<!-- 你的模态框内容 --> | ||
{{ content }} | ||
<button @click="$emit('update:visible', false)">关闭</button> | ||
@@ -42,119 +69,44 @@ </div> | ||
</template> | ||
<script setup lang="ts"> | ||
defineProps<{ | ||
visible: boolean | ||
}>() | ||
</script> | ||
``` | ||
2. 在应用中使用: | ||
3. 在应用中使用: | ||
```typescript | ||
import { createModalContext } from 'vue-modal-core' | ||
import MyModal from './MyModal.vue' | ||
import { makeModal } from './dialog'; | ||
import MyModal from './MyModal.vue'; | ||
// 创建模态框上下文 | ||
const { makeModal, ModalRenderer } = createModalContext({ | ||
baseZIndex: 1000, // 基础 z-index | ||
allowMultiple: true, // 是否允许多个模态框同时存在 | ||
debug: false // 是否开启调试日志 | ||
}) | ||
// 创建模态框实例 | ||
const modal = makeModal(MyModal) | ||
const modal = makeModal(MyModal); | ||
// 打开模态框 | ||
modal.open({ | ||
// 传入 props(除了 visible) | ||
title: '标题', | ||
content: '内容' | ||
}) | ||
// 传入 props | ||
content: 'Hello, World!' | ||
}); | ||
// 关闭模态框 | ||
await modal.close() | ||
setTimeout(() => { | ||
modal.close(); | ||
}, 3000); | ||
// 检查模态框是否可见 | ||
const isVisible = modal.isVisible() | ||
``` | ||
3. 在 App.vue 中挂载渲染器: | ||
4. 在应用根组件中挂载渲染器: | ||
```vue | ||
<!-- App.vue --> | ||
<script setup lang="ts"> | ||
import { ModalRenderer } from './dialog'; | ||
</script> | ||
<template> | ||
<div> | ||
<!-- 你的应用内容 --> | ||
<modal-renderer /> | ||
</div> | ||
<Teleport to="body"> | ||
<ModalRenderer /> | ||
</Teleport> | ||
<!-- Page Content --> | ||
</template> | ||
``` | ||
## 高级特性 | ||
### 关闭前钩子 | ||
你可以使用 `onBeforeClose` 钩子来控制模态框的关闭行为: | ||
```typescript | ||
import { onBeforeClose } from 'vue-modal-core' | ||
// 在模态框组件中 | ||
onBeforeClose(async () => { | ||
// 返回 false 可以阻止模态框关闭 | ||
const shouldClose = await askUser() | ||
return shouldClose | ||
}) | ||
``` | ||
### 多模态框管理 | ||
```typescript | ||
// 创建多个模态框实例 | ||
const modal1 = makeModal(MyModal, Symbol('Modal1')) | ||
const modal2 = makeModal(MyModal, Symbol('Modal2')) | ||
// 控制是否允许多个模态框同时显示 | ||
const { makeModal, ModalRenderer } = createModalContext({ | ||
allowMultiple: false // 设置为 false 时会自动关闭之前的模态框 | ||
}) | ||
``` | ||
### TypeScript 支持 | ||
库提供完整的 TypeScript 类型支持,可以获得完整的类型提示: | ||
```typescript | ||
import type { ExtractComponentOptions } from 'vue-modal-core' | ||
// 模态框的 props 类型会自动推导 | ||
const modal = makeModal(MyModal) | ||
modal.open({ | ||
// 这里会获得完整的类型提示 | ||
}) | ||
``` | ||
## API 参考 | ||
### createModalContext 配置项 | ||
| 参数 | 类型 | 默认值 | 说明 | | ||
|------|------|--------|------| | ||
| baseZIndex | number | 1000 | 模态框基础 z-index 值 | | ||
| allowMultiple | boolean | true | 是否允许多个模态框同时存在 | | ||
| debug | boolean | false | 是否开启调试日志 | | ||
### Modal 实例方法 | ||
| 方法 | 参数 | 返回值 | 说明 | | ||
|------|------|--------|------| | ||
| open | props: ExtractComponentOptions<C> | void | 打开模态框 | | ||
| close | - | Promise<boolean> | 关闭模态框 | | ||
| isVisible | - | boolean | 获取模态框可见状态 | | ||
## 注意事项 | ||
1. 确保在模态框组件中正确处理 `visible` prop 和 `update:visible` 事件 | ||
2. `onBeforeClose` 钩子必须在组件的 setup 函数或 `<script setup>` 中使用 | ||
3. 多个 `onBeforeClose` 钩子会按照后进先出(LIFO)的顺序执行 | ||
## API 文档 | ||
@@ -169,3 +121,2 @@ | ||
baseZIndex?: number; // 基础 z-index 值 | ||
enableAnimation?: boolean; // 是否启用动画 | ||
allowMultiple?: boolean; // 是否允许多个模态框同时存在 | ||
@@ -172,0 +123,0 @@ debug?: boolean; // 是否启用调试模式 |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
507
4.54%0
-100%25161
-2.66%159
-23.56%