7

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.

1
  • this won't take effect as expected when I switch route - isn't this the case for onBeforeRouteLeave ? onBeforeRouteUpdate is for current route. Commented Sep 5, 2021 at 16:22

2 Answers 2

12

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>
Sign up to request clarification or add additional context in comments.

Comments

6

I don't have enough rep to comment, but the above accepted answer does have a slight difference in operation.

Options API:

watch: {
  '$route': {
    handler(oldValue, newValue) => {}
  }
}

composition API:

setup() {
  const route = useRoute();
  watch(route, (newValue, oldValue) => {});
}

In the composition API, the oldValue will just be a clone of newValue (the same object), whereas in the options API, the oldValue will actually be the previous route (useful in many scenarios).

2 Comments

Do you know how to get the oldValue in the Composition API? If its possible at all.. Been struggling with this for a while and realised it only seems to be working with the Options API and you the only other resource I've seen which reports on this Thanks!
route = useRouter()? Maybe route = useRoute()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.