Skip to content

可显示 (Showable)

用于弹窗、抽屉等「可显示/隐藏」内容的共享状态与生命周期,基于 createInjectionState,在父级提供上下文后,子组件可获取同一套 show/closestatus 等。

hoci 引入:

ts
import {
  onShowableHide,
  onShowableShow,
  showableRef,
  useShowableContextProvider,
  useShowableInstance
} from "hoci";

快速开始

vue
<script setup>
import {
  showableRef,
  useShowableContextProvider,
  useShowableInstance
} from "hoci";
import { defineComponent, h } from "vue";

// 1. 创建 showableRef 用于外部控制
const dialogRef = showableRef();

// Wrapper 仅使用 useShowableContextProvider,并通过 expose 暴露 show 供外部 ref 调用
const Provider = defineComponent({
  setup(_, { expose }) {
    const { show, close } = useShowableContextProvider();
    expose({ show, close });
    return () => h(Content);
  }
});

// Content 仅使用 useShowableInstance
const Content = defineComponent({
  setup() {
    const instance = useShowableInstance();
    const {
      show, // 打开
      close, // 关闭
      confirm, // 确认(status = "ok")
      reject, // 拒绝(status = "reject")
      cancel, // 取消(status = "cancel")
      visible, // 是否可见
      status // 当前状态
    } = instance;

    return () => h("div", { class: "flex flex-col gap-2" }, [
      h("div", { class: "flex gap-2" }, [
        h("button", { onClick: () => show() }, "打开"),
        h("button", { onClick: () => close() }, "关闭"),
        h("button", { onClick: confirm }, "确认"),
        h("button", { onClick: cancel }, "取消")
      ]),
      h("div", `visible: ${visible.value}, status: ${status.value}`)
    ]);
  }
});
</script>

<template>
  <div class="flex flex-col gap-2">
    <!-- 在 Wrapper 外部的作用域中调用,通过 ref 挂载 -->
    <button @click="dialogRef?.show()">
      外部触发
    </button>
    <Provider ref="dialogRef" />
  </div>
</template>

弹窗组件示例

一个完整的弹窗组件示例,展示如何使用 useShowableInstance 控制弹窗的显示/隐藏和状态。

使用 expose 暴露show方法

在 Wrapper 层中,必须使用 expose({ show })show 方法暴露给外部。这样通过 ref 绑定挂载后,外部才能通过 dialogRef.value?.show() 打开弹窗。若缺少 expose,ref 上拿不到 show,外部调用会无效。

带参数打开

调用 instance.show(data) 时传入参数,内部通过 onShowableShowuseShowableInstance({ onShow }) 接收参数。

API

Provider

方法说明
useShowableContextProvider()在父组件调用一次,提供 showable 上下文。必须在子组件使用 useShowableInstance 之前调用。

useShowableInstance(options?)

在已有 provider 的子树内调用,返回当前 showable 的实例 API 与响应式状态。

返回值:

属性 / 方法类型说明
show(data?)(data?: PARAMETERS) => void打开(将 visible 设为 true,status 设为 "none"),可传入参数传递给事件监听器
close(status?)(status?: ShowableStatus) => void关闭并设置 status(默认 "none")
confirm()() => void关闭且 status 为 "ok",同时触发 "confirm" 事件
reject()() => void关闭且 status 为 "reject",同时触发 "reject" 事件
cancel()() => void关闭且 status 为 "cancel",同时触发 "cancel" 事件
visibleComputedRef<boolean>是否显示
headerComputedRef<string | boolean>标题
statusComputedRef<ShowableStatus>当前状态

无 provider 时:会抛出错误 "useShowableContextStore must be used after useShowableContextProvider"

UseShowableInstanceOption

属性类型说明
onShow(parameters?: PARAMETERS) => void | Promise<void>每次调用 show() 时触发,接收传入的参数。当 REQUIREtrue 时,参数为必填
onHide(status: ShowableStatus) => void每次调用 close() 时触发,接收关闭时的 status
onConfirm() => voidstatus 变为 "ok" 时调用(通过 confirm()
onReject() => voidstatus 变为 "reject" 时调用(通过 reject()
onCancel() => voidstatus 变为 "cancel" 时调用(通过 cancel()
headerMaybeRefOrGetter<string | false>同步到 store 的标题,可以是字符串、false(隐藏)、或 ref/computed

onShowableShow / onShowableHide

方法说明
onShowableShow(fn, options?)注册回调,当调用 show() 时触发。回调接收 show() 传入的参数。options.immediate(默认 true)控制是否立即调用(如果 showable 已可见)。注意:当回调的参数类型为必填时,immediate 选项不可用(类型层面禁止)
onShowableHide(fn)注册回调,当调用 close() 时触发。回调接收关闭时的 status

showableRef()

返回 shallowRef<Showable<T> | null>(null),用于在外部持有「可显示实例」的引用。通过模板 ref 绑定到 Dialog 等组件后,外部可调用 dialogRef.value?.show()

注意:被 ref 绑定的组件需在 setup 中使用 expose({ show }) 显式暴露 show 方法,否则 ref 上无法访问到 show

类型

类型说明
ShowableStatus"none" | "ok" | "cancel" | "reject" - 关闭时的状态
ShowableInstance<PARAMETERS, REQUIRE?>useShowableInstance 的返回类型(含 show/close/confirm/reject/cancel 与响应式状态)
Showable<PARAMETERS, REQUIRE?>仅含 show(data?) 的接口,用于 showableRef 等。当 REQUIREtrue 时,show() 参数必填
ShowableResult<T>结果对象形态(含 id、status、data 等,可按需扩展)