I’m trying to migrate a Vue 2.x app to Vue 3.x. Unfortunately, for the past two days, I’m struggling to find working solution to this simple issue :
My application is for mobile device and, at the top of the screen, I have a top bar with 2 contextual buttons on the left and on the right. These buttons trigger methods that are related to the view loaded in my <router-view/>
and hosted in it.
My Vue 2 app it worked perfectly well following the advice of this post :
[Vue 2] App.vue
<template>
<app-bar>
<bar-btn @click="$refs.routerView[$route.meta.leftBtn.methodName]($route.meta.leftBtn.arguments)">Left btn</bar-btn>
<div>View title</div>
<bar-btn @click="$refs.routerView[$route.meta.rightBtn.methodName]($route.meta.rightBtn.arguments)">Right btn</bar-btn>
</app-bar>
<main>
<router-view ref="routerView"/>
</main>
</template>
Methods names and optional arguments where stored in my meta data of my routes :
[Vue 2] Router.js
{
name: 'View 1',
path: '/',
component: MyView1,
meta: {
requiresAuth: false,
leftBtn: { methodName: 'showLeftDialog', arguments: 'myArgument' }
rightBtn: { methodName: 'showRightDialog', arguments: 'myArgument' }
},
},
In Vue 2, I had access to the router-view instance by using: this.$refs.routerView
Unfortunately, it does not work anymore with Vue 3 !
After having spent a lot of time, I haven't found a proper way to get access to my child instance loaded in my <router-view/>
in order to trigger my methods hosted in it.
[Vue 3] This does NOT work:
Does not work:
this.$refs.routerView[this.$route.meta.leftBtn.methodName](this.$route.meta.leftBtn.arguments)
Does not work:
this.$router.currentRoute.value.matched[0].components.default.methods[this.$route.meta.leftBtn.methodName](this.$route.meta.leftBtn.arguments)
Does not work:
this.$refs.routerView.$refs => this is an empty object
Put it simply, how can I have access to the instance of child component loaded in router-view with Vue 3 ?
Any help on this would be very much appreciated.
Vue Router 4's <router-view>
exposes the rendered view component in a v-slot
prop that can be rendered with <component>
, to which you could apply a template ref:
<router-view v-slot="{ Component }">
<component ref="view" :is="Component" />
</router-view>
Then the component's methods can be accessed via $refs.view.$.ctx
:
<bar-btn @click="$refs.view.$.ctx[$route.meta.leftBtn.methodName]($route.meta.leftBtn.arguments)">Left btn</bar-btn>
<bar-btn @click="$refs.view.$.ctx[$route.meta.rightBtn.methodName]($route.meta.rightBtn.arguments)">Right btn</bar-btn>