Vue3手动挂载组件传递Vuex Store的迁移问题求助
Vue3手动挂载组件时$store未定义的问题解决思路
问题概述
原Vue2项目中通过手动实例化组件并传递store的方式正常工作,升级到Vue3(迁移兼容构建)后,改用第三方包手动挂载组件时,出现$store未定义的渲染警告,导致组件渲染失败。
Vue2工作代码
mountLegendGroup (legendElement, indicators, panel) { const Component = LegendGroup; const legendGroup = new Component({ propsData: { indicators: indicators.map(i => i.params), isUpper: panel.isUpper, panelUid: panel.params.uid }, store: this.$store }); legendElement.innerHTML = ''; legendGroup.$mount(legendElement, true); },
Vue3尝试代码(出现问题)
mountLegendGroup (legendElement, indicators, panel) { const Component = LegendGroup; Component.props = ['indicators', 'isUpper', 'panelUid']; legendElement.innerHTML = ''; mount(Component, { props: { 'indicators': indicators.map(i => i.params), 'isUpper': panel.isUpper, 'panelUid': panel.params.uid } }, legendElement); }
待挂载组件代码
<template> <div> <div class="legend-group"> <div class="left-group"> <div v-for="(indicator, index) in indicators" :key="index" > <LegendItem :key="index" :indicator="indicator" :panel-uid="panelUid" /> </div> </div> <div class="right-group"> <LegendMovePanel v-if="isMovable" :panel-uid="panelUid" /> <LegendExpandCollapse v-if="showExpandCollapse" :panel-uid="panelUid" /> <LowerOverlayDropdown v-if="!isUpper" :panel-uid="panelUid" /> </div> </div> </div> </template> <script> import { mapGetters } from 'vuex'; import LegendExpandCollapse from '@/components/modcharts/LegendExpandCollapse'; import LegendItem from '@/components/modcharts/LegendItem'; import LegendMovePanel from '@/components/modcharts/LegendMovePanel'; import LowerOverlayDropdown from '@/components/modcharts/LowerOverlayDropdown'; export default { components: { LegendExpandCollapse, LegendItem, LegendMovePanel, LowerOverlayDropdown }, computed: { ...mapGetters([ 'activeTheme', 'chartGetter', 'options' ]), isMovable () { const chart = this.chartGetter(); return !this.isUpper && chart.panels.length > 2; }, panelComputedHeightsEnabled () { return this.options.usePanelComputedHeight; }, resizablePanelsEnabled () { return this.options.panelResize; }, showExpandCollapse () { return ( !this.isUpper && !this.panelComputedHeightsEnabled && !this.resizablePanelsEnabled ); } }, props: { indicators: { type: Array, required: true }, isUpper: { type: Boolean, default: false }, panelUid: { type: String, required: true } } }; </script>
错误提示
[Vue warn]: Property "$store" was accessed during render but is not defined on instance.[Vue warn]: Unhandled error during execution of render function
解决思路
方案1:使用Vue3原生createApp手动挂载(推荐)
Vue3中不再支持通过new Component的方式实例化组件,正确的手动挂载方式是通过createApp创建应用实例,并注入Vuex store:
import { createApp } from 'vue' mountLegendGroup (legendElement, indicators, panel) { const Component = LegendGroup; legendElement.innerHTML = ''; // 创建应用实例并传入props const app = createApp(Component, { indicators: indicators.map(i => i.params), isUpper: panel.isUpper, panelUid: panel.params.uid }) // 注入Vuex store,确保组件能访问$store app.use(this.$store) // 挂载到目标元素 app.mount(legendElement) }
方案2:适配第三方包mount-vue-component
如果坚持使用该第三方包,需要通过provide传递$store,让组件能获取到Vuex实例:
mountLegendGroup (legendElement, indicators, panel) { const Component = LegendGroup; legendElement.innerHTML = ''; mount(Component, { props: { indicators: indicators.map(i => i.params), isUpper: panel.isUpper, panelUid: panel.params.uid }, // 提供$store给组件 provide: { $store: this.$store } }, legendElement); }
关键原因说明
Vue2中直接给组件实例传递store参数即可让组件继承store,但Vue3的组件依赖于应用实例的上下文注入,手动挂载时必须通过app.use(store)或者provide的方式将store传递给组件,否则组件无法访问$store,进而导致mapGetters调用失败、渲染报错。
内容的提问来源于stack exchange,提问作者zwsaile
相关产品推荐
相关产品推荐

