str
str

Reputation: 44969

Best Practice for Reacting to Params Changes with Vue Router

When using Vue Router with routes like /foo/:val you have to add a watcher to react for parameter changes. That results in somewhat annoying duplicate code in all views that have parameters in the URL.

This could look like the following example:

export default {
    // [...]
    created() {
        doSomething.call(this);
    },
    watch: {
        '$route' () {
            doSomething.call(this);
        }
    },
}

function doSomething() {
    // e.g. request API, assign view properties, ...
}

Is there any other way to overcome that? Can the handlers for created and $route changes be combined? Can the reuse of the component be disabled so that the watcher would not be necessary at all? I am using Vue 2, but this might be interesting for Vue 1, too.

Upvotes: 33

Views: 17265

Answers (3)

Pirooz Jenabi
Pirooz Jenabi

Reputation: 682

vue3 and script setup:

watch(route, () => { fetch()})

in import:

import { watch } from 'vue';
import { useRoute } from 'vue-router';
const route = useRoute()

Upvotes: 3

Nikita G.
Nikita G.

Reputation: 720

I used this variant without :key prop on router-view component.

routes.js:

     {
        path: 'url/:levels(.*)',
        name: ROUTES.ANY_LEVEL,
        props: true,
        component: (): PromiseVue => import('./View.vue'),
      },

view.vue

<template>
    <MyComponent :config="config" />
</template>

---*****----

<script>
data: () => ({ config: {} }),
methods: {
    onConfigurationChanged(route) {
      const { params } = route

      if (params && params.levels) {
        this.config = // some logic
      } else {
        this.config = null
      }
    },
  },
  beforeRouteUpdate(to, from, next) {
    this.onConfigurationChanged(to)
    next()
  },
}
</script>

Inside the component, I use the config as a property. In my case, reactivity is preserved and the component is updated automatically from parameter changes inside the same URL. Works on Vue 2

Upvotes: 0

str
str

Reputation: 44969

One possible answer that I just found thanks to a GitHub issue is the following.

It is possible to use the key attribute that is also used for v-for to let Vue track changes in the view. For that to work, you have to add the attribute to the router-view element:

<router-view :key="$route.fullPath"></router-view>

After you add this to the view, you do not need to watch the $route anymore. Instead, Vue.js will create a completely new instance of the component and also call the created callback.

However, this is an all-or-nothing solution. It seems to work well on the small application that I am currently developing. But it might have effects on performance in another application. If you really want to disable the reuse of the view for some routes only, you can have a look at setting the key's value based on the route. But I don't really like that approach.

Upvotes: 56

Related Questions