一口气拿下vue-router所有知识点,薪资暴涨3000

Posted 前端呆头鹅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一口气拿下vue-router所有知识点,薪资暴涨3000相关的知识,希望对你有一定的参考价值。

一口气拿下vue-router所有知识点,薪资暴涨3000

一 vue路由基础使用【固定路由的配置和使用】

首先我们展示一下router使用后的效果。

首先启动服务后,输入路由http://localhost:8080/#/A,到达页面A,展示页面A内容,点击页面上按钮或者将url切换为http://localhost:8080/#/B,到达页面B,展示页面B内容。

怎样配置

  1. 创建两个文件src/views/a.vue和src/views/b.vue,用来展示路由切换效果。
// src/views/a.vue
<template>
  <div>
    <h1>我是页面a</h1>
  </div>
</template>
// src/views/b.vue
<template>
  <div>
    <h1>我是页面b</h1>
  </div>
</template>
  1. 创建src/router/index.js文件,在src/router/index.js中引入router必要文件,导出router对象。

src/router/index.js文件代码示例如下。

import Vue from "vue";
import VueRouter from "vue-router";
import a from "../views/a.vue";
import b from "../views/b.vue";

// 注册路由插件
Vue.use(VueRouter);

// 定义路由规则
const routes = [
  
    path: "/B",
    name: "A",
    component: a,
  ,
  
    path: "/B",
    name: "B",
    component: b,
  ,
];

// 创建router对象
const router = new VueRouter(
  routes,
);

export default router;
  1. 在src/main.js中,在全局vue实例创建的时候,注入router对象。

src/main.js代码示例如下。

...
import router from "./router";
...
new Vue(
  router,
  ...
  render: (h) => h(App)
).$mount("#app");

这一步做了什么呢,我们可以将vue实例打印出来,看一下router写入前后,vue实例有什么变化。

// src/main.js
const vm1 = new Vue(
  router,
  //   store,
  render: (h) => h(App),
).$mount("#app");

const vm2 = new Vue(
  // router,
  //   store,
  render: (h) => h(App),
).$mount("#app");

console.log(vm1, vm2);

我们写了两个不同的Vue实例,两者唯一的区别是有无注入router,将它们打印出来后对比一下,可以看到,注入router的vue实例中增加了几个router相关的属性, r o u t e r 和 router和 routerroute属性被赋值。

点击打开后可以看到, r o u t e r 中 有 一 些 路 由 相 关 的 方 法 , router中有一些路由相关的方法, routerroute中有当前路由的信息。


这些信息已经挂载到了全局vue实例上,在页面中就可以直接使用了。

  1. 在App.vue中对应位置添加<router-view/>标签,该标签为路由组件的占位符,路由切换时,该标签会被替换成对应的路由组件。就达到了我们想要的效果。

在切换路由时,我们可以通过点击<router-link />标签或者手动更改url的方式进行页面切换,下面是一个带有<router-view/>标签和<router-link />标签的代码示例。

这里我们为router-link标签写上了一些样式,使展示更加美观。

<template>
  <div id="app">
    <router-link class="a" to='A'>跳往页面A</router-link>
    <router-link class="b" to='B'>跳往页面B</router-link>
    <router-view />
  </div>
</template>

<style>
.a,.b 
 border: 1px solid #42b983;
 padding: 5px 10px;
 margin: 5px;
 margin-top: 300px;
 color: #42b983;
</style>

怎样控制路由跳转

刚刚介绍了路由在html中使用标签进行跳转,但有时我们希望在js中跳转,该怎样操作呢?这就用到上面挂载在vue实例上的$router。代码示例如下。

this.$router.push('/b') // 根据路由文件中的path跳转到页面B
this.$route.query // 取得当前路由的参数
this.$router.push( name: 'B' ) // 根据路由文件中的name跳转到页面b
this.$router.replace('/b') // 在不记录当前的路由的情况下跳转到页面b,无法从b后退到当前路由
this.$router.go(-2) // 后退到历史某次访问的页面
this.$router.go(-1) === this.$router.back()

二 如何在路由中携带参数【动态路由的配置和使用】

刚才我们对于不同页面配置了不同固定路由。

不知你有没有注意到csdn的个人主页,小明的个人主页链接为https://blog.csdn.net/123,而小米的个人主页链接为https://blog.csdn.net/456,相同的页面对应的路由却不一样,似乎路由中携带了一个参数,用来区分不同用户,而路由指向的又是同一个页面,这是怎么回事呢?


怎样携带参数

我们再看上面配置的src/router/index.js文件route对象。

// src/router/index.js
const routes = [
  
    path: "/a",
    name: "A",
    component: a,
  ,
  
    path: "/b",
    name: "B",
    component: b,
  ,
];

这时我们希望将b页面的路由达到上面携带不同参数,有指向同一个页面的效果,我们将这种路由叫做动态路由,动态路由的配置也很简单,对应位置前加冒号就可以,代码示例如下。

// src/router/index.js
const routes = [
  
    path: "/a",
    name: "A",
    component: a,
  ,
  
    path: "/b/:id", // 这里变化了哦
    name: "B",
    component: b,
  ,
];

这时我们可以看到,原来的路由http://localhost:8080/#/b已经访问不到该页面了,将路由变更为http://localhost:8080/#/b/1可以正常访问页面,将b/后面更改为任意值都可以访问到页面。

带有参数的动态路由也可以通过js指定name跳转。

this.$router.push( name: 'B', params:  id: 1  )

现在参数已经写入动态路由中了,怎么获取该参数呢?

怎样获取参数

  1. 使用 r o u t e . p a r a m s . i d 获 取 , 动 态 路 由 中 的 参 数 都 可 以 通 过 v u e 全 局 属 性 route.params.id获取,动态路由中的参数都可以通过vue全局属性 route.params.idvueroute下的params对象获取,代码示例如下。
<template>
  <div>
    <h1>我是页面b</h1>
    通过当前路由获取: $route.params.id 
  </div>
</template>

<script>
export default 
  name: B
;
</script>

  1. 使用props获取,使用该方法需要在route路由中配置props为true,代码示例如下。
// src/router/index.js
const routes = [
  
    path: "/a",
    name: "A",
    component: a,
  ,
  
    path: "/b/:id",
    name: "B",
    component: b,
    props:true,
  ,
];
<template>
  <div>
    <h1>我是页面b</h1>
    通过props获取:  id 
  </div>
</template>

<script>
export default 
  name: B,
  props: ["id"],
;
</script>

三 如何提取页面相同内容【嵌套路由的配置和使用】

刚刚我们在app.vue中写入了标签,该标签会被路由文件中配置的组件替换。

当前页面是这样的。

现在我们有了新的需求,在b页面中,我们希望可以再开辟一块自由区域,可以随着路由变化。

这时我们的b页面就是一个layout页面(布局页面),它里面包含一部分可以分化的内容,可以分化出不同页面。

具体到页面上,我们将实现下面的效果。


首先我们新建三个文件,将layout页面和内部的两个分化页面layoutA和layoutB准备好。

// src/view/LayoutA.vue
<template>
    <div>AAAAAAAA</div>
</template>
// src/view/LayoutB.vue
<template>
    <div>AAAAAAAA</div>
</template>
// src/component/Layout.vue
<template>
  <div>
    <div class="bar">header</div>
    <div class="content">
    <router-view />
    </div>
    <div class="bar">footer</div>
  </div>
</template>

<style lang="scss" scoped>
.bar 
    width: 100px;
    padding: 10px;
    text-align: center;
    background-color: green;
    padding:20px 0;
    color: #fff;
    width: 100%;

.content 
    background-color: khaki;
    height: 300px;
    color: green;
    line-height: 300px;
    width: 100%;
    font-size: 40px;

</style>

然后我们在src/router/index.js中修改router配置如下。

const routes = [
  ... ...
  
    path: "/b",
    name: "B",
    component: layout,
    children: [
      
        name: "LayoutA",
        path: "/b/a",
        component: LayoutA,
      ,
      
        name: "LayoutB",
        path: "/b/b",
        component: LayoutB,
      ,
    ],
  ,
];

当路由/b/a或者/b/b的时候,组件layout会替换app.vue中的标签,组件LayoutA或者LayoutB会替换组件layout中的标签。

就实现了上面的效果。

四 路由的两种模式有什么不同【hash和history的区别】

表现形式有什么区别

hash模式带有#号,#号后面的内容是我们的路由地址,history模式是正常的路由。

hash:http://localhost:8080/#/b

history:http://localhost:8080/b

实现原理有什么区别

hash模式:基于锚点也就是#号,当#后面的路由发生变化后,触发onhashchange事件,在事件中对页面进行操作。

history模式:基于h5中的historyAPI。

history.pushState() 在浏览器记录中添加一个新纪录,不向后端发送请求。

history.replaceState() 修改浏览器历史中当前历史记录,不向后端发送请求。

由于浏览器的url栏中始终显示最新的url记录,所以就好像触发了页面更新一样,其实并没有。

五 history模式的使用和问题

history模式配置和使用

history的配置很简单,在src/router/index.js中,创建路由实例时设置属性mode为history即可。

import Vue from "vue";
import VueRouter from "vue-router";
...

Vue.use(VueRouter);

const routes = [...];

const router = new VueRouter(
  mode: "history", // 在这里设置
  routes,
);

export default router;

现在我们再次访问刚才的页面。

现在使用http://localhost:8080/#/b/b已经访问不到啦,我们将#去掉,url更改为http://localhost:8080/b/b,页面出现了。

history浏览器请求问题

history模式中,在触发页面跳转时,我们使用history.pushState() 在浏览器记录中添加一个新纪录,不向后端发送请求。

但如果我们使用浏览器触发跳转会怎样呢,比如直接向浏览器中输入url后,或者点击页面刷新。

有的同学有讲,我在开发过程中经常直接使用浏览器跳转呀,没遇到问题,这是因为我们使用的vue脚手架已经帮我们解决了这个问题,但是当代码打包,上线后,问题就出现了,浏览器会告诉我们,找不到该页面。

这是因为我们使用代码去进行跳转/b/b,实际上不是真实的跳转,不会向服务端发送请求,而浏览器跳转会向后端发送请求,后端一看,没有/b/b这个请求路径呀,就会报错。

所以使用history模式,需要在服务端配置一下。

如果我们使用的是node做服务端时,可以通过配置中间件/插件(connect-history-api-fallback)来实现对history的支持。把这个插件在node.js服务端引入后注册就好了。

如果我们使用的是nginx服务,在nginx的配置文件中配置当找不到对应页面的时候返回首页就好啦。

因为我们主要是讲vue-router,这里就不展开讲解node服务和nginx服务啦。

六 浅析vue-router实现原理【面试必备】

hash模式实现原理

  1. url中#后面的内容作为路径地址
  2. 监听hashchange事件
  3. 根据当前路由地址找到对应组件重新渲染

history模式实现原理

  1. 通过history.pushState()方法改变地址栏
  2. 监听popstate事件
  3. 根据当前路由地址找到对应组件重新渲染

七 怎样实现自己的vue-router

vue-router是什么

vue-router是什么?实现vue-router从何下手,首先我们来分析它的使用,在src/router/index.js中,我们引入vue-router,使用vue.use()注册了它,又new了它的实例,最后导出。

import Vue from "vue";
import VueRouter from "vue-router";

Vue.use(VueRouter);

const routes = [...];

const router = new VueRouter(
  mode: "history",
  routes,
);

export default router;

Vue.use方法里面的参数可以是一个对象或者一个函数,当它是一个函数的时候它会被执行,当它是一个对象的时候,会执行对象内部的install函数,那么vue-router是什么呢。

下面我们使用new创建了一个vue-router实例,这里可以看出,vue-router是一个类(类也是对象哦)。

我们现在对vue-router有了一定的认知,它是一个类,里面包含install方法,它有一个构造函数,可以对new时传入的参数进行处理。

知道了它是什么,我们就可以向着这个方向开发啦。

实现一个vue插件【install】

实现一个插件需要几步?首先我们写一个含有install方法的类。

export default class VueRouter 
  static install(Vue)  

该类作为插件,被vue调用install方法的时候,会传入一个参数,就是vue构造函数。在install中我们可以保存vue构造函数和对vue构造函数做改动。

首先我们可以在install中对插件是否已安装做判断,已安装状态下直接返回。我们可以通过设置一个变量来记录。

然后将vue构造函数记录在一个变量中,以备使用。

let _Vue = null;
export default class VueRouter 
  static install(Vue) 
    // 判断当前插件是否被安装
    if (VueRouter.install.installed) 
      return;
    
    VueRouter.install.installed = true;
    // 将vue构造函数记录到全局变量
    _Vue = Vue;
  

最后对vue构造函数做一定的修改,我们刚才有提到,我们创建vue实例的时候,将返回的router传入了vue实例中。

new Vue(
  router,
  render: (h) => h(App),
).$mount("#app");

传入之后vue做了什么呢,要知道router对于vue来说只是一个插件而已,vue原本的逻辑是不包括对router的处理的,所以router处理的这一步应该是写在vue-router的install中的。

在创建vue实例前,vue会调用钩子函数beforeCreate,这部分逻辑可以使用混入/mixin写入。

let _Vue = null;
export default class VueRouter 
  static install(Vue) 
    ...
    // 把创建vue实例时候传入的router对象注入到vue实例上
    _Vue.mixin(
      beforeCreate() 
        if (this.$options.router) 
          _Vue.prototype.$router = this.$options.router;
        
      ,
    );
  

我们使用混入,为vue实例的beforeCreate钩子函数添加了一段逻辑,这里的this.$options指的就是我们在创建vue实例时传入的对象。比如下面的代码中,option就是含有router和render属性的对象。

new Vue(
  router,
  render: (h) => h(App),
).$mount("#app");

还记得前面我们有将vue实例打印出来看吗,option中添加了router后,vue实例的$router就有值啦。

现在install函数就写好了,我们的vuerouter已经是一个合格的插件了,我们盘点一下一共做了几步。

  1. 判断当前插件是否被安装
  2. 将vue构造函数记录到全局变量
  3. 为vue添加beforeCreate逻辑,增加对router信息的处理。

以上是关于一口气拿下vue-router所有知识点,薪资暴涨3000的主要内容,如果未能解决你的问题,请参考以下文章

我三年开发经验,从字节跳动抖音组离职后,一口气拿到 15 家公司 Offer,薪资再一次直线上涨

我五年Java开发经验,从字节跳动抖音组离职后,一口气拿到16家公司Offer,薪资再一次直线上涨~

最好的姐妹一口气拿下了8个测试岗的大厂offer,让我很有面子

2022互联网大厂薪资大比拼

气愤!3年后端开发,薪资还不如我眼中的“切图仔”...

开发五年涨薪无望,搞懂了这六大技术终于拿下美团offer,薪资45K