VUE学习笔记---初识VueRouter

前言

Vue Router啥用呢,其实就是前端来更改页面路径的一个玩意,一般来说,网页的跳转都是要后台来控制的,现在有了它,前端自己就可以定义路由。当然,后台得提供一个默认渲染页面index.html,所以有了这玩意,做个单页面应用就很方便。

正文

实现原理

Vue的思想就是一切皆组件,那么开发单页面应用的时候,它在加载页面的时候不会加载整个页面,而只加载指定的组件,那么当页面路径的改变的时候,并不是去更新页面,而是更新里面的组件。它的实现有两种模式:Hash模式History模式,这个下面再讲。

基本例子

HTML

<div id="app">
  <p>
    <router-link to="{ name:'/foo',params:{} }">Go to Foo</router-link>
    //name 为路由的名称,params为参数
  </p>
  <router-view></router-view>       //留坑,加载路径下默认组件
</div>

JavaScript

import Foo from "@/components/Foo"
const routes = [
  {
    path: '/foo',
    component: Foo
  }
]
export default new VueRouter({
  routes
})

全局注册

//main.js
import router from "./router"
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

动态路由匹配

模式 路径 $route.params
/user/:username /user/evan { username: 'evan' }
/user/:username/post/:post_id /user/evan/post/123 { username: 'evan', post_id: '123' }

在组件中访问路由的参数方法:this.$router.params,此外还有this.$router.query(获取查询参数),this.$router.hash(获取hash值)

嵌套路由

<router-view>是最顶层的出口,当它匹配到的组件中还包含<router-view>那么就要用到嵌套路由,children就要出场了。

routes : [
  {
    path : '/user/:id',
    component : User,
    children : [
      {
        path : 'profile',
        component : UserProfile
      }
    ]
  }
]

编程式的导航

啥意思呢,上面的内容是讲怎么在html里面放一个a标签,下面要讲的是,怎么用js实现链接跳转。

router.push()

this.$router.push({name: 'user',params: {userId: 123}})
// 也可以简写一下
// 这个也适用于router-link的to属性
const userId = 123
this.$router.push({path: `user/${userId}` })

router.replace()

router.push()类似,区别就是,router.replace()不会向History添加新纪录,意思就是说不能通过go(-1)返回上一个路由

router.go()

跟原生JS的window.history.go()一个意思

命名视图

<router-view>加载的是路由下默认的组件,当一个路由下有好多个组件的时候,就需要给<router-view>加一个name属性,让它对应相应的组件。

<router-view name='a'></router-view>
import Bar form '@/component/Bar'
routes: [
  {
    path: '/',
    components: {
      default: Foo,
      a: Bar
    }
  }
]

重定向

routes: [
  {
    path: '/a',
    redirect: '/b'  //重定向到/b
  },
  {
    path: '/a',
    redirect: {
      name: 'foo'   //重定向到一个命名的路由
    }
  },
  {
    path: '/a',
    redirect: to => {
      const { hash, params, query} = to;
      //根据hash  query.to  params.id 判断
      //最后 return 一个路径
    }
  }
]

别名

如果要实现路径不变,但是访问的是另外一个路由的东西,那么就要用到别名alias

{path: '/a',alias: '/b'}

/b/a的别名,当访问/b或者/a时候,路径不会改变,但是访问的视图都是/a路由下的视图

高级一点用法就是嵌套路由

{
  path: '/home',
  children: [
    {
      {
        path: 'foo',
        alias: ['/foo',foolis]
      }
    }
  ]
}

上面的代码中,当输入路径为/foo或者home/foolis或者home/foo渲染的都是相同的视图

路由传参

前面提到可以通过parms={}传递参数,在组件中获取参数

<div> {{ $route.params.id }} </div>

这种方式会形成高度耦合,更高明的方式就是用props

{path: '/user/:id',props: true}

props设置为true时,route.params将会变成组件属性,组件中就可以直接使用{{ id }}获取参数id

{path: '/user/:id',props: {name: 'world'}}

传给组件一个对象

props也可以用函数模式(获取查询参数的id)

const router = new VueRouter({
    routes: [
      {path: '/user/:id',props: (route) => ({ query: route.query.id })}
    ]
})

导航守卫

啥是导航守卫呢,就好比假如每一个url路径代表一扇门,那么就有很多个门,有一个人穿过这些门,每两个门中间的路上有那么一个摄像头,那么摄像头就是导航守卫,它就能知道这个人从哪扇门过来的,准备去哪扇门。

参数和查询改变并不需要去另外一扇门,所以摄像头就看不到,遇到这种情况就需要用到beforeRouteUpdate

全局守卫

const router = new VueRouter({})
router.beforeEach((to, from, next) => {
  // 不管函数体内作何判断,最终都必须调用next()
})

上面注册了一个全局前置守卫,一旦有一个导航被出发的时候,它就会调用。next()可以传递参数,当传递一个路由的时候就会中断当前的导航转向去另外一个导航,当参数为false时,返回from的路由。

与全局前置守卫对应的还有一个后置守卫afterEach(),但是后置守卫是没有next参数的

路由独享的守卫

可以直接在路由配置上定义一个beforeEnter守卫

routes: [
  {
    path: '/foo',
    beforeEnter((to,from,next) => {

    })
  }
]

组件内的守卫

export default{
  data() {
    return {}
  },
  beforeRouteEnter(to, from, next) {
    //渲染组件前调用
    //不!能!使用this,因为实例还没创建呢
  },
  beforeRouteUpdate(to, from, next) {
    // 路由更变但是视图没咋变的时候调用
    // 比如参数或者查询内容的变化
    // 可以使用this,因为组件被复用了
  },
  beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以使用this
    // 主要用来防止用户未保存就离开页面
  }
}

beforeRouteEnter 虽然不能访问this,但是可以传一个回调next来访问实例

beforeRouteUpdate(to, from, next) {
  next(vm => {
      // 通过vm访问组件实例
  })
}

beforeRouteEnter是唯一一个可以回调的守卫

完整的导航流程

  1. 全局的beforeEach守卫
  2. 重用组件中的beforeRouteUpdate守卫
  3. 路由配置里面的beforeEnter守卫
  4. 解析异步路由组件
  5. 在被激活的组件里调用beforeEnter
  6. 调用全局的beforeResolve守卫
  7. 导航被确认
  8. 调用全局的afterEach

路由元信息

{
  path: '/foo',
  meta: {
    requireIsLogin: true
  }
}

meta字段就是元信息,它的值可以随便定义,它有啥用,主要是给页面加了一个验证,假如有一些页面需要登录权限,那么就可以根据这个元字段来标识这些页面。下面用代码来实现

router.beforeEach((to, from, next) => {
  if(to.match.some(record => record.meta.requireIsLogin)) {
    if(!isLogin) {
      next({
          path: '/login',
          query: { redirect: to.fullPath }
      })
    }else{
      next()
    }
  }else{
    next()  // 一定要调用next()
  }
})

滚动行为

使用前端路由,当切换到新路由后,页面默认保持的的是原来的滚动位置,如果想让它滚动到顶部就像重新加载的一样,就需要用到scrollBehavior

const router = new VueRouter({
    routes:[],
    scrollBehavior(to, from, savedPosition) {
      if(savedPosition) {
        return savedPosition
      }else{
        return {x: 0, y: 0}
      }
    }
})

第三个参数savedPosition仅且仅当是通过浏览器的前进/后退按钮触发的才可用。

如果返回一个falsy(不是false),或者一个空对象,那么不会发生滚动。

如果要模拟滚动到锚点

scrollBehavior(to, from, savedPosition) {
  if(to.hash) {
    return {
      selector: to.hash
    }
  }
}

当然也可以延迟滚动,用Promise来实现

scrollBehavior(to, from, savedPosition) {
  return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({x: 0, y: 0})
      },500)
  })
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,711评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,079评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,194评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,089评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,197评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,306评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,338评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,119评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,541评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,846评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,014评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,694评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,322评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,026评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,257评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,863评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,895评论 2 351

推荐阅读更多精彩内容

  • 前言 vue-router是什么:是vue.js官方的路由管理器和vue.js的核心深度的集成,让开发者更加简单的...
    GUAN_one阅读 3,695评论 0 2
  • 学习目的 学习Vue的必备技能,必须 熟练使用 Vue-router,能够在实际项目中运用。 Vue-rout...
    _1633_阅读 91,996评论 3 58
  • vue-router学习笔记 安装 并且如果在一个模块化工程中使用它,必须要通过Vue.use()明确地安装路由功...
    EL_PSY_CONGROO阅读 579评论 0 0
  • VUE Vue :数据驱动的M V Vm框架 m :model(后台提供数据),v :view(页面),vM(模板...
    wudongyu阅读 5,391评论 0 11
  • 导航守卫 导航表示路由正在发生改变。vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种...
    oWSQo阅读 689评论 0 0