Vue3如何从组件获取渲染后的DOM元素并接入VueX 4?
Vue3 动态创建组件并注入 VueX Store 的实现方案
示例组件 LayerComponent
<script> export default { data() { return { count: 0 } } } </script> <template> <button @click="count++">You clicked me {{ count }} times.</button> </template>
需求说明
需要在另一个组件的mounted钩子中,动态创建上述组件并获取其渲染后的DOM元素,用于第三方库调用,同时确保组件能正常访问VueX Store(VueX 4版本)。
Vue2 中的实现方式
此前在Vue2中通过以下方式实现,运行正常:
import Vue from "vue"; import LayerComponent from "./LayerComponent"; // ...其他代码 mounted() { const lsComponent = Vue.extend(LayerComponent) const domElement = new lsComponent({ store: this.$store, }).$mount(); let htmlElement = domElement.$el; // 此时可将该DOM元素用于原生JS逻辑 }
Vue3 中的问题与正确实现
尝试直接用createApp并调用use(this.$store)的方式无法正常工作,因为use方法接收的是插件而非已实例化的Store对象。以下是两种可行的实现方案:
方案一:复用当前应用上下文(推荐)
通过createVNode和render创建组件,直接复用当前组件的应用上下文,确保Store可正常访问:
import { createVNode, render } from 'vue' import LayerComponent from './LayerComponent.vue' export default { mounted() { // 创建临时容器 const container = document.createElement('div') // 创建组件VNode,复用当前应用上下文以继承Store const vnode = createVNode(LayerComponent) vnode.appContext = this.$.appContext // 渲染组件到容器 render(vnode, container) // 获取渲染后的DOM元素 const htmlElement = container.firstElementChild // 将元素添加到页面(按需调整) document.body.appendChild(htmlElement) // 组件销毁时清理资源,避免内存泄漏 this.$once('hook:beforeUnmount', () => { render(null, container) document.body.removeChild(htmlElement) }) } }
方案二:创建独立App实例并注入Store
通过createApp创建独立应用实例,将当前Store注入全局属性:
import { createApp } from 'vue' import LayerComponent from './LayerComponent.vue' export default { mounted() { const container = document.createElement('div') // 创建App实例 const app = createApp(LayerComponent) // 将当前Store注入全局属性,使组件可通过this.$store访问 app.config.globalProperties.$store = this.$store // 挂载组件到容器 const vm = app.mount(container) const htmlElement = vm.$el document.body.appendChild(htmlElement) // 组件销毁时卸载App并清理DOM this.$once('hook:beforeUnmount', () => { app.unmount() document.body.removeChild(htmlElement) }) } }
以上两种方案均可实现Vue3中动态创建组件并确保Store正常访问的需求,推荐方案一,因为更轻量且能直接继承当前应用的所有上下文配置。
内容的提问来源于stack exchange,提问作者Sharful Islam
相关产品推荐
相关产品推荐

