Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't router.currentRoute.path reactive?

I have an app which is contained in this div:

<div id="app" v-bind:style='{backgroundColor: backgroundColor}'>
  ... the app ...
</div>

The routing is done following the example in the documentation (this is a webpack project):

import Vue from 'vue/dist/vue.js'
import VueRouter from 'vue-router'
import ComponentOne from './component1.vue'
import ComponentTwo from './component2.vue'

Vue.use(VueRouter)

const routes = [{
        path: '/foo',
        component: ComponentOne
    },
    {
        path: '/bar',
        component: ComponentTwo
    }
]

const router = new VueRouter({
    routes // short for `routes: routes`
})

const app = new Vue({
    router,
    data: {
        day: "Monday"
    },
    computed: {
        backgroundColor: function () {
            console.log(JSON.stringify(router.currentRoute))
            if (router.currentRoute.path == "/foo") {
                return "green"
            } else {
                return "blue"
            }
        }
    }
}).$mount('#app')

I wanted the background to be dependent on the current route (router.currentRoute.path).

But, the solution above does not work, because router.currentRoute.path is not detected by the Vue instance as having changed (is not reactive).

What is the correct way to access the dynamic router data from within the Vue instance?

like image 873
WoJ Avatar asked Jul 26 '17 13:07

WoJ


People also ask

Is Vue router reactive?

One of Vue's most distinctive features is the unobtrusive reactivity system.

How do I access my Vue 3 router?

Using <router-view> and <router-link> There are two directives our Vue application gives us to use in our template: <router-view /> - When a route is navigated to in the browser, this is where the component is rendered. For example, in our code going to / will render the Home component where we list <router-view /> .

How do I get the current URL in Vue?

If you are using Vue without Vue Router then you need to an use window object. But, If you are using Vue Router then you can use a route object.


2 Answers

The router object created via new VueRouter is not reactive because Vue has no way to know to watch and update any object outside of its scope.

Passing router in the Vue config object is what allows the current route to be watched, but you need to reference it via this.$route:

if (this.$route.path == "/foo") {
  ...
}

You can also access the entire router object via this.$router, but its data is not reactive.


And if you are using Vue 2 with composition api setup() approach you can do this:

    import { computed } from '@vue/composition-api'
    export default {
      setup (props, context) {
        const params = computed ( () => context.root.$route.params)
        const path = computed( () => context.root.$route.path)
like image 54
thanksd Avatar answered Sep 22 '22 03:09

thanksd


I found on Vue's documentation page that tracks the router using watch for transition animations. Not sure if this is a best practice but you can use to.path or from.path to grab the path instead.

// then, in the parent component,
// watch the `$route` to determine the transition to use
watch: {
  '$route': (to, from) => {
    const toDepth = to.path.split('/').length
    const fromDepth = from.path.split('/').length
    this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
  }
}
like image 45
Zachery Ng Avatar answered Sep 21 '22 03:09

Zachery Ng