Vue Router 入门

安装:

官方文档              官方API文档

npm install vue-router
// router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
// 模块化工程中,Vue.use() 是必须的
Vue.use(VueRouter);
// 抛出模块,用于跟组件注册
const router = new VueRouter({
  // ...
});
export default router
// main.js 需要引入 router
import router from './router/index.js';
// vue根组件注册 router
new Vue({
  router: router
});

 单页应用:

<!-- 单文件项目,可使用全局的script标签,省略前三步 -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

最简单的例子

<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!-- 使用 router-link 组件来导航. -->
    <!-- 通过传入 `to` 属性指定链接. -->
    <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</div>
<script>
// 1. 定义 (路由) 组件。(可以从其他文件 import 进来)
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是通过 Vue.extend() 创建的组件构造器,或者,只是一个组件配置对象。
const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]
// 3. 创建 router 实例,然后传 `routes` 配置 (还有其他配置参数)
const router = new VueRouter({
  routes: routes
})
// 4. 创建和挂载根实例。让整个应用都有路由功能
const app = new Vue({
  router
  // ...
})
</script>

组件可以通过 "this.$router" 访问路由器,通过 "this.$route" 访问当前路由。  官方完整例子


routes:

1. 动态路由匹配:  [ "path" ]

// 有如下 routes 配置
routes: [
  // 动态路径参数 以冒号开头
  { path: '/user/:id', component: User }
]
// 像 /user/foo 和 /user/bar 都将映射到相同的路由。
// User 组件内可以访问路径参数 "id"
console.log(this.$route.params);        // { id: 'foo' }
// 像 /user/:username/post/:post_id 的多段"路径参数"
console.log(this.$route.params);        // { username: 'evan', post_id: '123' }

注意,当使用路由参数时,如从 /user/foo 导航到 /user/bar ,组件实例会被复用,其生命周期函数将不会被调用

2. 嵌套路由: [ "children" ]

// 组件的模板需要添加一个 <router-view>
const User = {
  template: `
    <div class="user">
      <h2>User {{ $route.params.id }}</h2>
      <router-view></router-view>
    </div>
  `
}
const router = new VueRouter({
  routes: [{ 
    path: '/user/:id', component: User,
    // children 配置与 route 类似
    children: [
      // 当 /user/:id/profile 匹配成功,UserProfile 会被渲染在 User 的 <router-view> 中
      { path: 'profile', component: UserProfile }, 
      // 当 /user/:id/posts 匹配成功,UserPosts 会被渲染在 User 的 <router-view> 中
      { path: 'posts', component: UserPosts }, 
      // 当你访问 /user/foo 时,User 的出口是不会渲染任何东西,需要提供一个"空的"子路由
      { path: '', component: UserHome }
    ]
  }]
})

注意,以 "/" 开头的嵌套路径会被当作根路径,合理做法是使用"空路径"(" ")。    官方完整例子

3. 单视图组件注册:  [ "component" ]

<div>
  <router-view></router-view>
</div>
<script>
const Foo = { template: `<div>Foo</div>` }
const router = new VueRouter({
  routes: [{
    path: '/',
    // 通过本文件定义
    component: Foo
  }, {
    path: '/user',
    // 通过 异步懒加载 外部文件
    component: () => import('./User.vue')
  }]
})
</script>

4. 多视图组件注册:  [ "components"   <router-view name="a"> ]             官方完整例子     嵌套命名视图例子

<div>
  <!-- 同一个路由地址下显示多个"路由视图" -->
  <router-view class="view one"></router-view>
  <router-view class="view two" name="a"></router-view>
  <router-view class="view three" name="b"></router-view>
</div>
<script>
// 假设已经引入或定义组件 Foo/Bar/Baz
const router = new VueRouter({
  routes: [{
    path: '/',
    // 有别于"component"只能注册单个组件,"components"可以注册多个组件
    components: {
      // 匿名使用"default"注册
      default: Foo,
      a: Bar,
      b: Baz
    }
  }]
})
</script>

5. 命名路由:  [ "name" ]

const router = new VueRouter({
  routes: [{
    path: '/user/:userId',
    // 用于 路由跳转
    name: 'user',
    component: User
  }]
})
// 使用"声明式"路由跳转
// <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
// 使用"函数式"路由跳转
// router.push({ name: 'user', params: { userId: 123 }})

6. 路由 跳转/替换:  [ "<router-link>" | "router.push()" ]

方法1,声明式,使用 <router-link :to="..."> 创建 a 标签来定义导航链接。

<!-- :to="..." 的规则与 函数式 的一致,等效 router.push({name:'user',params:{userId:123}}) -->
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
<!-- 添加"replace"后,本路径会替换当前"history"记录,等效 router.replace({path:'/user/123'}) -->
<router-link :to="/user/123" replace>
<!-- 当 <router-link> 对应的路由匹配成功,将自动设置 class 属性值 .router-link-active。 -->

方法2,编程式使用 router.push(...)

// 若路径已用"name"命名,可以用 name 代替 path
router.push({ path: 'home' })
// "/user?plan=private"
router.push({ name: 'user', query: { plan: 'private' }})
// 注意:如果提供了 path,params 会被忽略,正确写法如下:(已定义 userId=123 )
router.push({ path: `/user/${userId}` }) // -> /user/123
// 替换当前路由(覆盖当前的history记录),用法与 .push() 一致
router.replace(...)
// 前进/后退,n 是整数,负数表示后退
router.go(n)

 

7. 重定向 & 别名 :  [ "redirect" & "alias" ]

const router = new VueRouter({
  routes: [
    // 重定向
    // 当用户访问 /a时,URL 将会被替换成 /b
    { path: '/a', redirect: '/b' },
    // 重定向到指定 name
    { path: '/a', redirect: { name: 'foo' }},
    // 别名
    // 当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a
    { path: '/a', component: A, alias: '/b' }
  ]
})

8. 路由组件传参:  [ "props" ]         个人完整在线demo

<div id="app">
  <router-link to="/vue_a/123">/vue_a/123</router-link><br>
  <router-link to="/vue_b">/vue_b</router-link><br>
  <router-link to="/vue_c?q=query">/vue_c?q=query</router-link><hr>
  <router-view></router-view>
</div>
<script>
const vue_a = {
  template: `<div> vue_a parmas.id : {{id}} </div>`,
  props: ['id']
}
const vue_b = {
  template: `<div> vue_b 静态props: {{vue_b_prop}} </div>`,
  props: ['vue_b_prop']
}
const vue_c = {
  template: `<div> vue_c query传参: {{query}} </div>`,
  props: ['query']
}
const router = new VueRouter({
  routes: [
    // 布尔模式。props 被设置为 true,route.params 将会被设置为组件属性。
    { path: '/vue_a/:id', component: vue_a, props: true },
    // 对象模式。传递静态参数
    { path: '/vue_b', component: vue_b, props: {vue_b_prop: 'aaaa'} },
    // 函数模式。URL /search?q=vue 会将 {query: 'vue'} 作为属性传递给 SearchUser 组件。
    { path: '/vue_c', component: vue_c, props: (route) => ({query: route.query.q}) }
  ]
});
new Vue({
  el: "#app",
  router
});
</script>

9. History模式:  [ "mode" ]

const router = new VueRouter({
  // 默认是"hash"
  mode: 'history',
  routes: [...]
})

 10. 路由元信息:  [ "meta" ]

// 官方的例子是利用"meta"的"requiresAuth"属性,实现组件是否需要权限访问
routes: [{
  path: '/foo',
  component: Foo,
  children: [{
    path: 'bar',
    component: Bar,
    // "requiresAuth"为自定义字段
    meta: { requiresAuth: true }
  }]
}]
// 在全局导航守卫中检查元字段:
router.beforeEach((to, from, next) => {
  // 获取目标路径是否带有指定的"meta"字段,并进行相关鉴权或操作
  if (to.matched.some(record => record.meta.requiresAuth)) {
    // 鉴定是否登陆,否则跳转到登陆页面
    if (!auth.loggedIn()) {
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    } else { next() }
  } else {
    next() // 确保一定要调用 next()
  }
})

滚动行为:  [ "scrollBehavior(to, from, savedPosition)" ]

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // return 期望滚动到哪个的位置,格式: { x: number, y: number }
    // scrollBehavior 的值就是{x:number,y:number}格式的对象
  }
})

导航守卫:

1. 全局守卫

const router = new VueRouter({ ... })
// 全局前置守卫
router.beforeEach((to, from, next) => { ... })
// 全局后置钩子,不接受next()
router.afterEach((to, from) => { ... })

2. 路由独享守卫

const router = new VueRouter({
  routes: [{
    path: '/foo',
    component: Foo,
    // 路由独享守卫
    beforeEnter: (to, from, next) => { ... }
  }]
})

3. 组件内的守卫

const Foo = {
  template: `...`,
  // 不能访问'this',但可以通过next()回调参数访问当前组件,如下
  beforeRouteEnter (to, from, next) {
    next(vm => { ... })
  },
  // 可以访问'this',只有在动态路径之间跳转才触发
  beforeRouteUpdate (to, from, next) { ... },
  // 可以访问'this',只有在非动态路径之间跳转才触发,该函数常用于判断用户是否保存,否则阻止跳转,如下
  beforeRouteLeave (to, from, next) {
    if (confirm) { next(); } else { next(false) }
  }
}

注意"next()" 钩子函数必须调用

 

完整的导航解析流程

个人在线demo


遇到的问题总结:

1. 父级路由不能含有 "name" 属性,否则会提示如下错误:

2. 关于路由的两种模式: hash模式history 模式

视觉上的区别是:hash模式下,主机名后面带有"#",更多查看 其他博客

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值