Frontend Development 11 min read

Converting State‑Driven Dialogs to Command‑Style Calls with the useCommandComponent Hook

This article explains how to convert state‑driven Element‑Plus Dialog components into a command‑style API using a custom useCommandComponent hook, discusses the drawbacks of traditional Dialog handling, outlines required component conventions, provides implementation code, and offers practical usage examples for Vue developers.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Converting State‑Driven Dialogs to Command‑Style Calls with the useCommandComponent Hook

The article starts by describing the "Dialog hell" problem: every Dialog component requires an extra visible variable and often duplicate logic in both parent and child components, leading to cumbersome state management.

It then demonstrates a basic MyDialog component built from Element‑Plus Dialog, showing the typical template and script code needed to control visibility and emit events.

Several existing solutions are examined, including command‑style wrappers that separate the Dialog logic into separate files or JSX components, each with its own trade‑offs such as increased maintenance cost or additional dependencies.

The core solution introduced is the useCommandComponent hook, which allows developers to keep the original component implementation while invoking it imperatively. Example usage in a parent component:

import { ElButton } from 'element-plus';
import { useCommandComponent } from '../../hooks/useCommandComponent';
import Comp from './components/Comp.vue';
import MyDialog from './components/MyDialog.vue';

const myDialog = useCommandComponent(MyDialog);

And in the template:

<ElButton @click="myDialog({ title: '父组件弹窗' })"> 打开弹窗 </ElButton>
<Comp text="子组件1" />
<Comp text="子组件2" />

Child components can also obtain the hook and call the dialog in the same way, preserving the original MyDialog code.

Two conventions are recommended for any dialog component to work smoothly with the hook:

The component must expose a visible prop that drives its open/close state.

The component must emit a close event when it is dismissed.

If a component does not follow these conventions, the hook can still be used by manually passing the appropriate props (e.g., dialogVisible ) and calling myDialog.close() in custom event handlers.

The article provides the full source code of useCommandComponent , which creates a temporary container, mounts the component with createVNode , handles app context merging, and defines a close method to clean up the rendered vnode.

import { AppContext, Component, ComponentPublicInstance, createVNode, getCurrentInstance, render, VNode } from 'vue';

export interface Options {
  visible?: boolean;
  onClose?: () => void;
  appendTo?: HTMLElement | string;
  [key: string]: unknown;
}

export interface CommandComponent {
  (options: Options): VNode;
  close: () => void;
}

// ...implementation details omitted for brevity

A patch is also discussed that merges the current instance's provides into the new component's app context, ensuring injected dependencies are available.

Finally, the author encourages readers to like, comment, and bookmark the post if the hook helps their development workflow.

frontendVueHooksComposition APIDialoguseCommandComponent
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.