This is an example of routes I have in my application:
{
path: "/something",
name: "SomeRoute",
component: SomeComponent,
meta: {showExtra: true},
},
{
path: "/somethingElse",
name: "SomeOtherRoute",
component: SomeOtherComponent,
},
Then I have the following component, which as you will notice has two script
tags, one with composition API, one without:
<template>
<div>
This will always be visible. Also here's a number: {{ number }}
</div>
<div v-if="showExtra">
This will be hidden in some routes.
</div>
</template>
<script setup lang="ts">
import type { RouteLocationNormalized } from "vue-router"
import { ref } from "vue"
const number = 5
const showExtra = ref(true)
const onRouteChange = (to: RouteLocationNormalized) => {
showExtra.value = !!to.meta?.showExtra
}
</script>
<script lang="ts">
import { defineComponent } from "vue"
export default defineComponent({
watch: {
$route: {
handler: "onRouteChange",
flush: "pre",
immediate: true,
deep: true,
},
},
})
</script>
This works correctly: when I enter a route with meta: {showExtra: false}
it hides the extra div, otherwise it shows it.
What I want to do, however, is achieve the same by only using the composition API, in other words removing the second <script>
tag entirely. I have tried this:
<script setup lang="ts">
import type { RouteLocationNormalized } from "vue-router"
import { ref } from "vue"
import { onBeforeRouteUpdate } from "vue-router"
// ...
// same as before
// ...
onBeforeRouteUpdate(onRouteChange)
</script>
But this won't take effect as expected when I switch route. I'm aware of the watch
function I could import, but I'm unsure how to get the meta information about the route and how to appease the type checker.
You can convert your watcher to composition api by importing watch
method from vue
<script lang="ts">
import { defineComponent, vue, watch } from "vue"
import { useRoute } from "vue-router"
export default defineComponent({
setup() {
const route = useRoute()
watch(route, (to) => {
showExtra.value = !!to.meta?.showExtra
}, {flush: 'pre', immediate: true, deep: true})
},
})
</script>