插件窝 干货文章 手动挂载Vue3.0组件到DOM节点的方法

手动挂载Vue3.0组件到DOM节点的方法

组件 节点 挂载 vue 564    来源:    2024-10-30

、问题

在VUE应用中,经常会使用一些非vue实现的js库,这些js库可能要求外部传入一些界面DOM节点,但该界面通常是vue组件定义,无法直接传递给js库,那么vue组件如何生成DOM节点传递给js库?比如在开发地图应用中,地图引擎通常是纯js库,当点击地图上的信息点弹出信息框时,地图引擎库要求传入信息框的dom节点,通常该信息框由vue组件实现,无法直接传递给地图引擎库,需将vue组件手动生成dom节点,才能传递给地图引擎。

二、手动挂载vue组件

vue组件手动生成dom节点主要通过以下两个函数:

(1)createVNode函数:由组件对象生成一个虚拟节点。

(2)render函数:把一个虚拟节点挂载到一个dom节点上。

因此要把vue组件挂载在dom节点可以如下调用:

import  myPopupComp from "./myPopupComp .vue"; //我们写的组件
import {createVNode,render,getCurrentInstance} from "vue";
const parentNode=docuemnt.createElement("div");
const vNode=createVNode(myPopupComp,{}/*组件要传递的参数*/);
const appContext=getCurrentInstance().appContext;/*获取app的上下文,
注意:如果getCurrentInstance没法返回当前的组件实例,
可以将函数放到组件的setup中执行,然后通过变量记录该实例。
也可以在主函数createApp时,把app传递进来。*/
vNode.appContext=appContext;/*将vue组件关联到当前app下管理,
如果这个appContext是单独创建,那么原来app相关的资源将不能用,
如:router,全局组件等等,都需要重新创建。*/
render(vNode,parentNode);//将组件挂载到parentNode下。

于是parentNode就包含了组件生成的节点,这个parentNode就可以挂载到地图的popup组件上。

注意:挂载时,需要将当前app的appContext传递给组件,否则组件不能使用当前app的资源,包括路由、界面框架、状态等全局组件,无法与当前app交互。

三、卸载vue组件

(1)手动卸载组件

手动挂载到dom节点的vue组件不会自动卸载,可能会造成内存泄漏(是否泄漏具体没研究过,但如果没有卸载,组件的onUnmounted不会被调用,导致有些内部的依赖该回调的功能出现问题)。卸载组件没有单独的方法,复用render方法:

render(null,parentNode);

(2)自动卸载组件

在某些情况下,我们想随着dom node的生命周期结束,一起自动卸载组件,如:地图的popup组件的生命周期是由地图管理的,地图删除popup节点时,删除对应的vue组件,可采用如下方式,增加对组件节点被删除事件的监听,在删除时,卸载vue组件:

parentNode.addEventListener("DOMNodeRemovedFromDocument",()=>render(null,parentNode));

四、与用createApp挂载的区别

将vue组件挂载到dom节点还有另一种方法,就是利用createApp直接创建一个app,然后mount到一个dom节点上。类似如下代码:

import {createApp} from "vue";
import myComp from "./myComp.vue"; //我的组件

//待挂载的节点
const domNode=document.CreateElement("div");
//创建app
const app=createApp(myComp,{/*组件的参数*/});
//将app挂载到节点上
app.mount(domNode);

这种方法的vue组件运行在独立的app下,无法使用主app所注册的路由、状态、界面框架等全局资源,如果要使用,需要重新建立主app所创建的环境。所以这种方式并不适合我们的使用场景。

五、小结

在Vue应用中,如果需要将某个vue组件提供给其他不支持vue的js框架,可采用此方法将vue组件生成的dom节点传递给框架,同时保持该vue组件可与当前应用交互。

到此这篇关于手动挂载Vue3.0组件到DOM节点的方法的文章就介绍到这了,更多相关Vue手动挂载到DOM节点内容请搜索插件窝以前的文章或继续浏览下面的相关文章希望大家以后多多支持插件窝!