只有 Vue Router 2 是与 Vue 2 相互兼容的,所以如果你更新了 Vue ,你也需要更新 Vue Router 。这也是我们在主文档中将迁移路径的详情添加进来的原因。 有关使用 Vue Router 2 的完整教程,请参阅 Vue Router 文档

Router 初始化

router.start 替换

不再会有一个特殊的 API 用来初始化包含 Vue Router 的 app ,这意味着不再是:

router.start({
  template: '<router-view></router-view>'
}, '#app')

你只需要传一个路由属性给 Vue 实例:

new Vue({
  el: '#app',
  router: router,
  template: '<router-view></router-view>'
})

或者,如果你使用的是运行时构建 (runtime-only) 方式:

new Vue({
  el: '#app',
  router: router,
  render: h => h('router-view')
})

{% raw %}

升级路径

运行 迁移助手 找到 router.start 被调用的示例。

{% endraw %}

Route 定义

router.map 替换

路由现在被定义为一个在 router 实例里的一个 routes 选项数组。所以这些路由:

router.map({
  '/foo': {
    component: Foo
  },
  '/bar': {
    component: Bar
  }
})

会以这种方式定义:

var router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo },
    { path: '/bar', component: Bar }
  ]
})

考虑到不同浏览器中遍历对象不能保证会使用相同的键值,这种数组的语法可以保证更多可预测的路由匹配。

{% raw %}

升级路径

运行 迁移助手 找到 router.map 被调用的示例。

{% endraw %}

router.on 移除

如果你需要在启动的 app 时通过代码生成路由,你可以动态地向路由数组推送定义来完成这个操作。举个例子:

// 普通的路由
var routes = [
  // ...
]

// 动态生成的路由
marketingPages.forEach(function (page) {
  routes.push({
    path: '/marketing/' + page.slug
    component: {
      extends: MarketingComponent
      data: function () {
        return { page: page }
      }
    }
  })
})

var router = new Router({
  routes: routes
})

如果你需要在 router 被实例化后增加新的路由,你可以把 router 原来的匹配方式换成一个包括你新添的加路由的匹配方式:

router.match = createMatcher(
  [{
    path: '/my/new/path',
    component: MyComponent
  }].concat(router.options.routes)
)

{% raw %}

升级路径

运行 迁移助手 找到 router.on 被调用的示例。

{% endraw %}

router.beforeEach changed

router.beforeEach 现在是异步工作的,并且携带一个 next 函数作为其第三个参数。

router.beforeEach(function (transition) {
  if (transition.to.path === '/forbidden') {
    transition.abort()
  } else {
    transition.next()
  }
})
router.beforeEach(function (to, from, next) {
  if (to.path === '/forbidden') {
    next(false)
  } else {
    next()
  }
})

subRoutes 换名

出于 Vue Router 和其他路由库一致性的考虑,重命名为children

{% raw %}

升级路径

运行 迁移助手 找到 subRoutes 选项的示例。

{% endraw %}

router.redirect 替换

现在用一个路由定义的选项作为代替。举个例子,你将会更新:

router.redirect({
  '/tos': '/terms-of-service'
})

成像下面的routes配置里定义的样子:

{
  path: '/tos',
  redirect: '/terms-of-service'
}

{% raw %}

升级路径

运行 迁移助手 找到 router.redirect 被调用的示例。

{% endraw %}

router.alias 替换

现在是你进行 alias 操作的路由定义里的一个选项。举个例子,你需要在你的routes定义里将:

router.alias({
  '/manage': '/admin'
})

配置这个样子:

{
  path: '/admin',
  component: AdminPanel,
  alias: '/manage'
}

如果你需要进行多次 alias 操作,你也可以使用一个数组语法去实现:

alias: ['/manage', '/administer', '/administrate']

{% raw %}

升级路径

运行迁移助手找到 router.alias 被调用的示例。

{% endraw %}

任意的 Route 属性 替换

现在任意的 route 属性必须在新 meta 属性的作用域内,以避免和以后的新特性发生冲突。举个例子,如果你以前这样定义:

'/admin': {
  component: AdminPanel,
  requiresAuth: true
}

你现在需要把它更新成:

{
  path: '/admin',
  component: AdminPanel,
  meta: {
    requiresAuth: true
  }
}

如果在一个路由上访问一个属性,你仍然会通过 meta 。举个例子:

if (route.meta.requiresAuth) {
  // ...
}

{% raw %}

升级路径

运行 迁移助手 找到任意的路由不在 meta 作用域下的示例。

{% endraw %}

URL 中的 Query 数组 [] 语法 移除

当传递数组给 query 参数时,URL 语法不再是 /foo?users[]=Tom&users[]=Jerry,取而代之,新语法是 /foo?users=Tom&users=Jerry,此时 $route.query.users 将仍旧是一个数组,不过如果在该 query 中只有一个参数:/foo?users=Tom,当直接访问该路由时,vue-router 将无法知道我们期待的 users 是个数组。因此,可以考虑添加一个计算属性并且在每个使用 $route.query.users 的地方以该计算属性代替:

export default {
  // ...
  computed: {
    // 此计算属性将始终是个数组
    users () {
      const users = this.$route.query.users
      return Array.isArray(users) ? users : [users]
    }
  }
}

Route 匹配

路由匹配现在使用 path-to-regexp 这个包,这将会使得工作与之前相比更加灵活。

一个或者更多的命名参数 改变

语法稍微有些许改变,所以以/category/*tags为例,应该被更新为/category/:tags+

{% raw %}

升级路径

运行 迁移助手 找到弃用路由语法的示例。

{% endraw %}

链接

v-link 指令已经被一个新的 <router-link> 组件指令替代,这一部分的工作已经被 Vue 2 中的组件完成。这将意味着在任何情况下,如果你拥有这样一个链接:

<a v-link="'/about'">About</a>

你需要把它更新成:

<router-link to="/about">About</router-link>

注意:<router-link>不支持target="_blank"属性,如果你想打开一个新标签页,你必须用<a>标签。

{% raw %}

升级路径

运行 迁移助手 找到 v-link 指令的示例。

{% endraw %}

v-link-active 也因为指定了一个在 <router-link> 组件上的 tag 属性而被弃用了。举个例子,你需要更新:

<li v-link-active>
  <a v-link="'/about'">About</a>
</li>

成这个写法:

<router-link tag="li" to="/about">
  <a>About</a>
</router-link>

<a>标签将会成为真实的链接 (并且可以获取到正确的跳转),但是激活的类将会被应用在外部的<li>标签上。

{% raw %}

升级路径

运行 迁移助手 找到 v-link-active 指令的示例

{% endraw %}

编程导航

router.go 改变

为了与 HTML5 History API 保持一致性,router.go 已经被用来作为 后退/前进导航router.push 用来导向特殊页面。

{% raw %}

升级路径

运行 迁移助手 ,找到 router.gorouter.push 指令被调用的示例。

{% endraw %}

路由选择:Modes

hashbang: false 移除

Hashbangs 将不再为谷歌需要去爬去一个网址,所以他们将不再成为哈希策略的默认选项。

{% raw %}

升级路径

运行 迁移助手 找到 hashbang: false 选项的示。

{% endraw %}

history: true 替换

所有路由模型选项将被简化成一个单个的mode 选项。你需要更新:

var router = new VueRouter({
  history: 'true'
})

成这个写法:

var router = new VueRouter({
  mode: 'history'
})

{% raw %}

升级路径

运行 迁移助手 找到 history: true 选项的示。

{% endraw %}

abstract: true 替换

所有路由模型选项将被简化成一个单个的mode 选项。你需要更新:

var router = new VueRouter({
  abstract: 'true'
})

成这个写法:

var router = new VueRouter({
  mode: 'abstract'
})

{% raw %}

升级路径

运行 迁移助手 找到 abstract: true 选项的示例。

{% endraw %}

路由选项:Misc

saveScrollPosition 替换

它已经被替换为可以接受一个函数的 scrollBehavior 选项,所以滑动行为可以完全的被定制化处理 - 甚至为每次路由进行定制也可以满足。这将会开启很多新的可能,但是简单的复制旧的行为:

saveScrollPosition: true

你可以替换为:

scrollBehavior: function (to, from, savedPosition) {
  return savedPosition || { x: 0, y: 0 }
}

{% raw %}

升级路径

运行 迁移路径 找到 saveScrollPosition: true 选项的示例。

{% endraw %}

root 换名

为了与 HTML 的<base> 标签保持一致性,重命名为 base

{% raw %}

升级路径

运行 迁移路径 找到 root 选项的示例。

{% endraw %}

transitionOnLoad 移除

由于 Vue 的过渡系统 appear transition control 的存在,这个选项将不再需要。

{% raw %}

升级路径

运行 迁移路径 找到 transitionOnLoad: true 选项的示例。

{% endraw %}

suppressTransitionError 移除

出于简化钩子的考虑被移除。如果你真的需要抑制过渡错误,你可以使用 try...catch 作为替代。

{% raw %}

升级路径

运行 迁移指令 找到 suppressTransitionError: true 选项的示例。

{% endraw %}

路由挂钩

activate 替换

使用 beforeRouteEnter 这一组件进行替代。

{% raw %}

升级路径

运行 迁移路径 找到 beforeRouteEnter 钩子的示例。

{% endraw %}

canActivate 替换

使用beforeEnter 在路由中作为替代。

{% raw %}

升级路径

运行 迁移路径 找到 canActivate 钩子的示例。

{% endraw %}

deactivate 移除

使用beforeDestroy 或者 destroyed 钩子作为替代。

{% raw %}

升级路径

运行 迁移路径 找到 deactivate 钩子的示例。

{% endraw %}

canDeactivate 替换

在组件中使用beforeRouteLeave 作为替代。

{% raw %}

升级路径

运行 迁移路径 找到 canDeactivate 钩子的示例。

{% endraw %}

canReuse: false 移除

在新的 Vue 路由中将不再被使用。

{% raw %}

升级路径

运行 迁移助手 找到 canReuse: false 选项的示例。

{% endraw %}

data 替换

$route属性是响应式的,所以你可以就使用一个 watcher 去响应路由的改变,就像这样:

watch: {
  '$route': 'fetchData'
},
methods: {
  fetchData: function () {
    // ...
  }
}

{% raw %}

升级路径

运行 迁移助手 找到 data 钩子的示例。

{% endraw %}

$loadingRouteData 移除

定义你自己的属性 (例如:isLoading),然后在路由上的 watcher 中更新加载状态。举个例子,如果使用 axios 获取数据:

data: function () {
  return {
    posts: [],
    isLoading: false,
    fetchError: null
  }
},
watch: {
  '$route': function () {
    var self = this
    self.isLoading = true
    self.fetchData().then(function () {
      self.isLoading = false
    })
  }
},
methods: {
  fetchData: function () {
    var self = this
    return axios.get('/api/posts')
      .then(function (response) {
        self.posts = response.data.posts
      })
      .catch(function (error) {
        self.fetchError = error
      })
  }
}