.markdown-body pre,.markdown-body pre>code.hljs{color:#333;background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#d14}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#009926}.hljs-bullet,.hljs-symbol{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}

公众号:暮北林
Q Q 群 : 一起学前端

Vue 3 实现函数调用组件的完整指南

在 Vue 3 中,有时我们需要动态创建和挂载组件,例如实现一个弹窗、通知或某些特定的交互组件。与直接在模板中定义组件不同,函数调用组件可以动态创建实例,同时便于灵活传参和事件处理。

本文将详细介绍如何使用 Vue3的createApp创建一个支持 props 和事件处理的函数调用组件,并提供两种不同的实现方式:templaterender


什么是函数调用组件?

函数调用组件是一种通过 JavaScript 函数动态创建 Vue 组件实例的实现方式。它的常见场景包括:

  • 弹窗(如 MessageBox
  • 通知组件(如 Toast
  • 特定交互(如动态表单、选择器)

其核心特点是:

  • 动态创建:不需要预定义在模板中。
  • 灵活传参:支持动态传递 props 和事件处理。
  • 销毁机制:组件可以在合适的时机被清理。

基础实现

我们将以一个名为 ChanceReassign 的组件为例,展示如何实现函数调用组件。组件支持 propsemit 事件。

1. 基础的 template 实现

在 Vue 3 中,createApp 是动态创建组件实例的核心工具。我们首先使用 template 方式:

import ChanceReassign from '@/components/chanceReassign/chanceReassign.vue';
import { createApp } from 'vue';
import VantInstall from '@/plugins/vantInstall'; // 假设你有一个 Vant 插件注册逻辑

export default function chanceReturn(props) {
  // 创建动态容器
  const container = document.createElement('div');
  container.classList.add('SHARE');
  document.body.appendChild(container);

  // 创建 Vue 应用实例
  const app = createApp({
    inheritAttrs: false, // 禁用默认属性继承
    setup(_, { attrs }) {
      return { props, attrs }; // 将 props 和 attrs 暴露给模板
    },
    template: `
      <ChanceReassign vv-bind="props" v-on="attrs" <!-- 动态传递组件属性和事件:props 包含传递给组件的所有参数,而 attrs 捕获了所有事件监听器的绑定。通过这样的绑定,组件既可以接收动态属性,也能正确触发父组件传递的事件。 -->/>
    `,
  });

  // 注册全局插件和组件
  VantInstall(app);
  app.component('ChanceReassign', ChanceReassign);

  // 挂载到容器
  const instance = app.mount(container);

  // 提供销毁方法
  instance.unmountApp = () => {
    app.unmount();
    document.body.removeChild(container);
  };

  return instance;
}


核心逻辑说明
  1. 动态容器创建:通过 document.createElement 创建一个 DOM 容器,供组件挂载。
  2. setup** 方法中解构 ****attrs**:将事件绑定 (onConfirmonClose 等) 通过 v-on="attrs" 动态传递给组件。
  3. 插件注册与全局组件:通过 VantInstall 或其他方式注册全局依赖,确保组件功能完整。
  4. 提供销毁机制:动态创建的容器需在组件卸载时清理,防止内存泄漏。
使用示例
import chanceReturn from '@/utils/chanceReturn';

const instance = chanceReturn({
  someProp: 'value',
  onConfirm: () => console.log('Confirmed!'),
  onClose: () => console.log('Closed!'),
});

// 销毁组件
setTimeout(() => {
  instance.unmountApp();
}, 5000);



2. 基于 render 的实现

render 函数比 template 更加灵活,适合动态处理逻辑更复杂的场景,例如插入 slots 或动态子组件。

import { createApp, h } from 'vue';
import ChanceReassign from '@/components/chanceReassign/chanceReassign.vue';
import VantInstall from '@/plugins/vantInstall'; // 假设你有一个 Vant 插件注册函数

export default function chanceReturn(props) {
  // 创建容器
  const container = document.createElement('div');
  container.classList.add('SHARE');
  document.body.appendChild(container);

  // 创建 Vue 应用实例
  const app = createApp({
    render() {
      // 使用 h 函数创建 VNode
      return h(ChanceReassign, {
        ...props, // 传递 props
        // 事件绑定,确保所有事件可以传递
        ...Object.fromEntries(
          Object.entries(props).filter(([key]) => key.startsWith('on'))
        ),
      });
    },
  });

  // 注册全局插件和组件
  VantInstall(app);
  app.component('ChanceReassign', ChanceReassign);

  // 挂载到容器
  const instance = app.mount(container);

  // 提供销毁方法
  instance.unmountApp = () => {
    app.unmount();
    document.body.removeChild(container);
  };

  return instance;
}


核心逻辑说明
  1. render** 函数**:通过 h 函数动态创建虚拟节点(VNode),支持动态绑定 propsattrs
  2. 事件过滤:通过 props 中以 on 开头的键动态绑定事件。
  3. template 的区别render 提供更灵活的逻辑控制,比如动态插入 slots
使用方式

template 实现类似:

const instance = chanceReturn({
  someProp: 'value',
  onConfirm: () => console.log('Confirmed!'),
});

instance.unmountApp();



两种方式对比
特性 template 实现 render 实现
简洁性 模板语法简单直观 JavaScript 逻辑稍复杂
动态性 支持动态 props 和事件绑定 支持动态 props、事件和复杂逻辑
插入 slots 支持 较难实现 易于实现
扩展性 中等
适用场景
  • 如果只是传递简单的 props 和事件,template 更易读。
  • 如果需要动态插入 slots 或实现复杂逻辑,建议使用 render

总结

通过 createApptemplaterender,我们可以轻松实现函数调用组件。根据场景选择适合的实现方式,可以帮助我们构建更加灵活、高效的 Vue 应用。

如果你有类似的需求,不妨尝试一下!

题外话

黑客&网络安全如何学习

今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。

1.学习路线图

在这里插入图片描述

攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去就业和接私活完全没有问题。

2.视频教程
网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我们和网安大厂360共同研发的网安视频教程,之前都是内部资源,专业方面绝对可以秒杀国内99%的机构和个人教学!全网独一份,你不可能在网上找到这么专业的教程。

内容涵盖了入门必备的操作系统、计算机网络和编程语言等初级知识,而且包含了中级的各种渗透技术,并且还有后期的CTF对抗、区块链安全等高阶技术。总共200多节视频,200多G的资源,不用担心学不全。
在这里插入图片描述
因篇幅有限,仅展示部分资料,需要见下图即可前往获取
在这里插入图片描述

🐵这些东西我都可以免费分享给大家,需要的可以点这里自取👉:网安入门到进阶资源

3.技术文档和电子书
技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本,由于内容的敏感性,我就不一一展示了。

在这里插入图片描述

因篇幅有限,仅展示部分资料,需要见下图即可前往获取
在这里插入图片描述

🐵这些东西我都可以免费分享给大家,需要的可以点这里自取👉:网安入门到进阶资源

4.工具包、面试题和源码
“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。

还有我视频里讲的案例源码和对应的工具包,需要的话见下图即可前往获取
在这里插入图片描述

🐵这些东西我都可以免费分享给大家,需要的可以点这里自取👉:网安入门到进阶资源

最后就是我这几年整理的网安方面的面试题,如果你是要找网安方面的工作,它们绝对能帮你大忙。

这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。

参考解析:深信服官网、奇安信官网、Freebuf、csdn等

内容特点:条理清晰,含图像化表示更加易懂。

内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…

在这里插入图片描述

因篇幅有限,仅展示部分资料,需要见下图即可前往获取
在这里插入图片描述

🐵这些东西我都可以免费分享给大家,需要的可以点这里自取👉:网安入门到进阶资源
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐