为什么 router.currentRoute.path 没有反应?

Why isn't router.currentRoute.path reactive?

我有一个包含在此 div 中的应用程序:

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

路由是按照example in the documentation(这是一个webpack项目)完成的:

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')

我希望背景依赖于当前路线 (router.currentRoute.path)。

但是,上述解决方案不起作用,因为 Vue 实例未检测到 router.currentRoute.path 已更改(不是反应性的)。

从 Vue 实例中访问动态路由器数据的正确方法是什么?

通过 new VueRouter 创建的 router 对象不是响应式的,因为 Vue 无法知道观察和更新其范围之外的任何对象。

Vue 配置对象中传递 router 允许监视当前路由,但您需要通过 this.$route:

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

您还可以通过 this.$router 访问整个 router 对象,但其数据不是反应性的。


如果您使用 Vue 2 和组合 api setup() 方法,您可以这样做:

    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)

我在 Vue 的 documentation 页面上找到了使用 watch 来跟踪路由器的过渡动画。不确定这是否是最佳做法,但您可以使用 to.path 或 from.path 来获取路径。

// 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'
  }
}