vue-router使用

路由简单使用

// App.vue
  <div id="app">
    <router-link  class="tab-item" to="/myTrip">我的行程</router-link>
    <router-link  class="tab-item" to="/messageCenter">消息中心</router-link>
    <router-link  class="tab-item" to="/friendManage">好友管理</router-link>
    <router-view></router-view>
  </div>
// router/index.js
export default new Router({
  routes: [
    {
      path: '/',
      redirect: () => import('../views/MyTrip.vue')
    }, {
      path: '/myTrip',
      component: () => import('../views/MyTrip.vue')
    }, {
      path: '/messageCenter',
      component: () => import('../views/MessageCenter.vue')
    }, {
      path: '/friendManage',
      component: () => import('../views/FriendManage.vue')
    }
  ]
})

在app.vue中
1. router-link标签会默认渲染成一个a标签,
2. to属性是该路由指向的路径,
3. 如果希望不已a标签来渲染,我们可以通过tag属性来指定所需渲染的标签名

在index.js中
1. routes用于定义路由,
2. path:为路由的路径,
3. component:为当前这个路径所渲染的路由组件,
4. redirect:为访问当前这个路径时,重定向的路由路径

编程式导航

编程式导航与声明式导航都可以实现路由的跳转。声明式导航是使用router-link通过a标签进行条船;而导航式,是通过click事件绑定,调用router上的方法进行跳转

  1. router.push,类似于window.history.pushState
	// 参数传递字符串
	this.$router.push('myTrip');
	// 参数传递对象形式
    this.router.push({path: 'myTrip'});
    // name需要在路由上事前起好名字
    this.router.push({name: 'trip', params:{id: '123'}});
    // 带查询参数,变成/myTrip?id=234
    this.router.push({path: 'myTrip', query:{id: '234'}});
  1. router.replace,类似于window.history.replaceState
    router.replacerouter.push很像,唯一一点不同就是,它不会向history中添加新历史,而是与它的方法名一样——替换当前的history记录
// 声明式
<router-link :to="..." replace>
// 导航式
this.$router.replace()
  1. router.go,类似于window.history.go
    这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)

// 后退一步记录,等同于 history.back()
router.go(-1)

// 前进 3 步记录
router.go(3)

// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)

路由参数

  • params传参,F5强制刷新参数会被清空(这里是通过name进行的路由跳转,如果使用path则无法获取到params传递的参数)
// 路由配置
{
  path: '/friendManage',
  // 一定要写name,params必须用name来识别路径
  name: 'friendManage',
  component: () => import('../views/FriendManage.vue')
}

// 参数传递
this.$router.push({
  name: `friendManage`,
  params: {
    user: 'Anna'
  }
})

// 参数接受
this.$route.params.user
  • query,由于参数适用路径传参的所以F5强制刷新也不会被清空
// 路由配置
{
  path: '/friendManage',
  // 一定要写name,params必须用name来识别路径
  name: 'friendManage',
  component: () => import('../views/FriendManage.vue')
}

// 参数传递
this.$router.push({
  name: `friendManage`,
  // 也可以使用path来进行路由跳转 path: '/friendManage'
  query: {
    user: 'Anna'
  }
})

// 参数接受
this.$route.query.user

嵌套路由

  • 嵌套路由从字面上理解,就是当前的界面,是由多层嵌套的组件组合而成

router/index.js

// router/index.js嵌套路由配置
 { path: '/user/:id', component: User,
  children: [
    {
      // 当 /user/:id/profile 匹配成功,
      // UserProfile 会被渲染在 User 的 <router-view> 中
      path: 'profile',
      component: UserProfile
    },
    {
      // 当 /user/:id/posts 匹配成功
      // UserPosts 会被渲染在 User 的 <router-view> 中
      path: 'posts',
      component: UserPosts
    }
  ]
}

要注意,以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径

message-center.vue

<div class="user">
  <h2>User {{ $route.params.id }}</h2>
  <router-view></router-view>
</div>

hash与history模式的区别

  • vue-router默认为hash模式,使用 URLhash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载
  • 如果用户考虑url的规范那么就需要使用history模式,因为history模式没有#号,是个正常的url适合推广宣传
  • 但是使用history模式还有一个问题就是,在访问二级页面的时候,做刷新操作,会出现404错误,就需要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面

导航守卫

  • 导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的 ,或者组件级的。

  • 全局守卫:router.beforeEachrouter.beforeResolve

  • 路由独享守卫:beforeEnter

  • 组件内守卫:beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave

  • router.beforeResolverouter.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用

  • 完整的导航解析流程

    1. 导航被触发。
    2. 在失活的组件里调用 beforeRouteLeave 守卫。
    3. 调用全局的 beforeEach 守卫。
    4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
    5. 在路由配置里调用 beforeEnter
    6. 解析异步路由组件。
    7. 在被激活的组件里调用 beforeRouteEnter
    8. 调用全局的 beforeResolve 守卫 (2.5+)。
    9. 导航被确认。
    10. 调用全局的 afterEach 钩子。
    11. 触发 DOM 更新。
    12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

Vue-Router的简单实现

let _Vue = null;
export default class VueRouter{
  // 静态方法不能被实例调用,只能通过类来调用。
  static install(Vue){
    // 1、判断当前插件是否已经被安装
    if (VueRouter.install.installed){
      return
    }
    VueRouter.install.installed = true;
    // 2、把Vue构造函数记录到全局变量
    _Vue = Vue;
    // 3、把创建Vue实例的时候传入到router对象注入到Vue实例上
    // 混入
    _Vue.mixin({
      beforeCreate(){
        // 判断只要在router实例上才执行,如果是组件的话就不再执行
        if (this.$options.router){
          _Vue.prototype.$router = this.$options.router;
          this.$options.router.init();

        }
      }
    })
  }

  constructor(options){
    this.options = options;
    this.routeMap = {};  // 解析路由规则
    this.data = _Vue.observable({   // 创建响应式对象
      current: '/'
    })
  }

  init(){
    this.initRouteMap();
    this.initComponents(_Vue);
    this.initEvent();
  }

  // 遍历所有的路由规则,把路由规则解析成键值对的形式,存储到routeMap中
  initRouteMap(){
    this.options.routes.forEach(route => {
      this.routeMap[route.path] = route.component;
    }) 
  }

  initComponents(Vue){
    const self = this;
    Vue.component('router-link', {
      props: {
        to: String
      },
      // template: `<a :href="to"><slot></slot></a>`
      render(h){
        return h('a', {
          attrs: {
            href: this.to
          },
          on: {
            click: this.clickHandler
          }
        }, [this.$slots.default])
      },
      methods: {
        clickHandler(e){
          history.pushState({}, '', this.to);
          this.$router.data.current = this.to;
          e.preventDefault();
        }
      }
    })

    Vue.component('router-view', {
      render(h){
        const component = self.routeMap[self.data.current];
        return h(component);
      }
    })
  }

  initEvent(){
    window.addEventListener('popstate', () => {
      this.data.current = window.location.pathname;
    })
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值