vue-router简单讲解

api文档

一. 安装和引入

直接下载 / CDN

https://unpkg.com/vue-router/dist/vue-router.js

Unpkg.com 提供了基于 NPM 的 CDN 链接。上面的链接会一直指向在 NPM 发布的最新版本。你也可以像https://unpkg.com/vue-router@2.0.0/dist/vue-router.js 这样指定 版本号 或者 Tag。

在 Vue 后面加载 vue-router,它会自动安装的:

// html
<script src="/path/to/vue.js"></script>
<script src="/path/to/vue-router.js"></script>
NPM
npm install vue-router --save

如果在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装路由功能:

// main.js

import Vue from 'vue'
import router from 'vue-router'

new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
});

如果使用全局的 script 标签,则无须如此(手动安装)。

构建开发版

如果你想使用最新的开发版,就得从 GitHub 上直接 clone,然后自己 build 一个 vue-router。

git clone https://github.com/vuejs/vue-router.git node_modules/vue-router
cd node_modules/vue-router
npm install
npm run build
引入
router.js 的配置

在src文件夹下创建router文件并新建一个router.js文件
首先引入 vue-router组件,Vue.use是用来加载全局组件的。那下面我们就开始看看这个VueRouter的写法和配置吧。

mode:

默认为hash,但是用hash模式的话,页面地址会变成被加个#号比较难看了http://localhost:8080/#/linkParams/xuxiao
所以一般我们会采用 history模式,它会使得我们的地址像平常一样。http://localhost:8080/linkParams/xuxiao

base
应用的基路径。例如,如果整个单页应用服务在 /app/ 下,然后 base 就应该设为 "/app/"。
一般写成 __dirname,在webpack中有配置。

routes
routes:就是我们的大核心了,里面包含我们所有的页面配置。
path:很简单,就是我们的访问这个页面的路径
name:给这个页面路径定义一个名字,当在页面进行跳转的时候也可以用名字跳转,要唯一哟
component:组件,就是咱们在最上面引入的 import ...了,当然这个组件的写法还有一种懒加载

懒加载的方式,我们就不需要再用import去引入组件了,直接如下即可。懒加载的好处是当你访问到这个页面的时候才会去加载相关资源,这样的话能提高页面的访问速度。
component: resolve => require(['./page/linkParamsQuestion.vue'], resolve)

//  router下的index.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router);

export default new Router({
  mode:"history",
  routes: [
    {
      path: '/more/fag',
      name: 'fag',
      component: fag
    },
    {
      path: '/',
      name: 'followers',
      component: follower
    },
    {
      path: '/followers',
      name: 'followers',
      component: follower
    },
    {
      path: '/likes',
      name: 'like',
      component: like
    },
    {
      path: '/more',
      name: 'more',
      component: more,
      children:[
        // {
        //   path: '/more/fag',
        //   name: 'fag',
        //   component: fag,
        // }
      ]
    }
  ]
})

二. router的使用

1. router传参
路由匹配参数

首先在路由配置文件router.js中做好配置。标红出就是对 /linkParams/的路径做拦截,这种类型的链接后面的内容会被vue-router映射成name参数。


3863065028-5932ec92b04df_articlex.png

代码中获取name的方式:

let name = this.$route.params.name; // 链接里的name被封装进了 this.$route.params
Get请求传参

如同:你完全可以在链接后加上?进行传参。
示例:http://localhost:8080/linkParamsQuestion?age=18
项目里获取:

let age = this.$route.query.age; //问号后面参数会被封装进 this.$route.query;
编程式导航

这里就开始利用vue-router讲发起跳转了。其实也非常简单,主要利用 <router-link>来创建可跳转链接,还可以在方法里利用 this.$router.push('xxx') 来进行跳转。

样例: <router-link to="/linkParams/xuxiao">点我不会怀孕</router-link>
上面的这个router-link就相当于加了个可跳转属性。

至于this.$router.push这里直接用官网的荔枝了

// 字符串,这里的字符串是路径path匹配噢,不是router配置里的name
this.$router.push('home')

// 对象
this.$router.push({ path: 'home' })

// 命名的路由 这里会变成 /user/123
this.$router.push({ name: 'user', params: { userId: 123 }})

// 带查询参数,变成 /register?plan=private
this.$router.push({ path: 'register', query: { plan: 'private' }})
导航钩子

导航钩子函数,主要是在导航跳转的时候做一些操作,比如可以做登录的拦截,而钩子函数根据其生效的范围可以分为 全局钩子函数、路由独享钩子函数和组件内钩子函数。

全局钩子函数

可以直接在路由配置文件router.js里编写代码逻辑。可以做一些全局性的路由拦截。

router.beforeEach((to, from, next)=>{
  //do something
  next();
});
router.afterEach((to, from, next) => {
    console.log(to.path);
});

每个钩子方法接收三个参数:

to: Route: 即将要进入的目标 路由对象

from: Route: 当前导航正要离开的路由

next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。

next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。

next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。

next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。

确保要调用 next 方法,否则钩子就不会被 resolved。

路由独享钩子函数

可以做一些单个路由的跳转拦截。在配置文件编写代码即可

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})
组件内钩子函数

更细粒度的路由拦截,只针对一个进入某一个组件的拦截。

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当钩子执行前,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}
其他知识点
滚动行为

在利用vue-router去做跳转的时候,到了新页面如果对页面的滚动条位置有要求的话,可以利用下面这个方法。

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // return 期望滚动到哪个的位置
  }
})

scrollBehavior 方法接收 to 和 from 路由对象。
第三个参数 savedPosition 当且仅当 popstate 导航 (mode为 history 通过浏览器的 前进/后退 按钮触发) 时才可用。
这里就不细致的讲了,文档都有也非常简单,记住有这个东西就行。

//所有路由新页面滚动到顶部:
scrollBehavior (to, from, savedPosition) {
  return { x: 0, y: 0 }
}

//如果有锚点
scrollBehavior (to, from, savedPosition) {
  if (to.hash) {
    return {
      selector: to.hash
    }
  }
}
路由元信息

这个概念非常简单,就是在路由配置里有个属性叫 meta,它的数据结构是一个对象。你可以放一些key-value进去,方便在钩子函数执行的时候用。
举个例子,你要配置哪几个页面需要登录的时候,你可以在meta中加入一个 requiresAuth标志位。

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      meta: { requiresAuth: true }
    }
  ]
})

然后在 全局钩子函数 beforeEach中去校验目标页面是否需要登录。

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    //校验这个目标页面是否需要登录
    if (!auth.loggedIn()) {  
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next() // 确保一定要调用 next()
  }
})
这个auth.loggedIn 方法是外部引入的,你可以先写好一个校验是否登录的方法,再import进 router.js中去判断。

项目中出现的问题

1. 切换路由后改变组件数据
//组件
<template>
    <div>{{header_msg}}</div>

</template>
export default {
         data(){
             return {
                  header_msg:'Get Followers',
             }
         },
          watch: {
            //不同path下  header_msg显示的信息不同
              '$route' (to, from) {
                  if(to.name === 'like'){
                      this.header_msg = 'Get Likes';
                      this.faq = false
                  }else if(to.name === 'more'){
                      this.header_msg = 'More';
                      this.faq = false
                  }else if(to.name === 'followers'){
                      this.header_msg = 'Get Followers';
                      this.faq = false
                  }else if(to.name === 'fag'){
                      this.faq = true
                  }
              }
          }
    }
2.解决vue-router嵌套路由(子路由)在history模式下刷新无法渲染页面的问题
异常描述:

本来使用的是vue-router的hash模式,但是hash模式下url需要带“#”符号,不仅看起来不舒服,而且有些场景下是会破坏路由中的"#"(微信分享页面就会把"#"后边的内容处理掉),所以就需要使用history模式,然后就让后端改下nginx配置:

 location / { try_files $uri $uri/ /index.html; } 

vue-router使用history模式+使用嵌套路由:

const router = new Router({
    mode: 'history',
    routes: [
        {
            path: '/',
            component: mall,
            name: 'mall'
        },
        ……

        //我的银行卡
        {
          path: '/myCard',
          meta: { requireAuth: true },
          component: myCard,
          name: 'myCard',
          children:[
            { path:'', component: card},
            { path:'add', component: add}
          ]
        }
         ……
    ]
})

访问路由和嵌套路由页面,显示正常,但是刷新页面的时候,嵌套路由页面css样式失效了:

解决问题:

先考虑的主Vue中以Import的方式引入静态样式文件,的确可行,但是最后发现,直接修改index.html文件中的静态文件引入路径就OK了:

修改前:

<link rel="stylesheet" href="./static/css/layout.css">

修改后

<link rel="stylesheet" href="/static/css/layout.css">
原理:

./ 是指用户所在的当前目录(相对路径);

/ 是指根目录(绝对路径,项目根目录),也就是项目根目录;

对于hash模式,根路径是固定的,就是项目的根目录,但是history模式下,以 / 开头的嵌套路径会被当作根路径,所以使用“./”引入文件,就会找不到文件了,因为文件本身就是在项目根目录下的,并不在嵌套路径这个目录下。

总结,无论hash模式还是history模式,可以直接使用“/”从项目根目录引入静态文件。

3. Vue默认首页router激活一直存在
异常描述:

在给router-link-active添加完样式后在发现默认路由('/')样式一直存在。
解决:给router-link添加exact属性

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

推荐阅读更多精彩内容