MENU

Vue路由使用笔记

July 9, 2022 • vue

基本使用

安装

npm i vue-router

配置

./router/index.js

import VueRouter from "vue-router";

import About from "../components/About";
import Home from "../components/Home";

export default new VueRouter({
  routes: [
    {
      path: "/about",
      component: About,
    },
    {
      path: "/home",
      component: Home,
    },
  ],
});

应用插件

import Vue from "vue";
import App from "./App.vue";

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

Vue.config.productionTip = false;

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

使用

<template>
  <div id="app">
    <router-link to="/about" class="router-link" active-class="active">about</router-link>
    <router-link to="/home" class="router-link" active-class="active">home</router-link>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: "App",
  components: {},
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

.router-link {
  margin: 2rem;
  transition: all 0.2s;
}

.active {
  font-size: larger;
}
</style>

几个注意点

  1. 一般的,我们将路由组件放在./pages/目录下,而./components/目录下只放静态组件路由切换
  2. 路由切换时,其他非路由选中的页面被销毁
  3. 每个组件都有 $route 属性,存储自己的路由信息
  4. 整个应用只有一个 router,可以通过组件的 $router 属性获取
  5. /可以理解为根目录下路由,使用 to 的时候要加/

多级路由

配置

import VueRouter from "vue-router";

import About from "../pages/About";
import Home from "../pages/Home";
import InnerA from "../pages/InnerA";
import InnerB from "../pages/InnerB";

export default new VueRouter({
  routes: [
    {
      path: "/about",
      component: About,
    },
    {
      path: "/home",
      component: Home,
      children: [
        { path: "ia", component: InnerA },
        { path: "ib", component: InnerB },
      ],
    },
  ],
});

使用

<template>
  <div>
    <h2>homepage</h2>
    <router-link to="/home/ia" class="router-link" active-class="active">linkA</router-link>
    <router-link to="/home/ib" class="router-link" active-class="active">linkB</router-link>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: "a-Home",
};
</script>

<style scoped>
.router-link {
  margin: 2rem;
  transition: all 0.2s ease-in-out;
  font-size: 1rem;
}

.active {
  font-size: 2rem;
}
</style>

注意

  1. 在上级(一级)路由添加 children 配置项,里面的子路由配置path 不需要加/
  2. 使用的时候,to 属性内容需要跟上父级路由,可以理解为从根目录下路由开始

命名路由

目的:简化跳转书写

当路由路径较长时,可以给特定路由一个 name,然后使用 router-link 时可以通过name 跳转

export default new VueRouter({
  routes: [
    {
      path: "/about",
      component: About,
    },
    {
      path: "/home",
      component: Home,
      children: [
        {
          path: "ia",
          component: InnerA,
          children: [{ path: "msg", component: Msg, name: "msg" }],//here
        },
        {
          path: "ib",
          component: InnerB,
        },
      ],
    },
  ],
});

路由传参 query

对象配置传参

:to="{
        name: 'msg',
        query: {
          id: msg.id,
          item: msg.title,
        },
      }"

接收参数

computed: {
    id() {
      return this.$route.query.id;
    },
    title() {
      return this.$route.query.item;
    },
  },

路由传参 params

配置占位符

{
          path: "ia",
          component: InnerA,
          children: [{ path: "msg/:id/:item", component: Msg ,name:'msg'}],
        },

传参

字符串写法

:to="`/home/ia/msg/${msg.id}/${msg.title}`"

对象写法

:to="{
        name: 'msg',
        params: {
          id: msg.id,
          item: msg.title,
        },
      }"
使用 params 传参时,不能使用 path,只能使用 name

接收

id() {
      return this.$route.params.id;
    },
    title() {
      return this.$route.params.item;
    },

两种传参区别

  • query 方式生成的 url 为/xx?id=id,params 方式生成的 url 为 xx/id
  • path 只能使用 query 方式
  • params 方式需要注意的是需要定义路由信息如:path: '/xx/:id',这样才能进行携带参数跳转,否则 url 不会进行变化,并且再次刷新页面后参数会读取不到
  • router-link 是 v-for 渲染的情况下,使用 params 参数可以让 active-class 生效,因为这个选项是根据路由地址来计算的,在 query 情况下地址不变,只变参数,会出现渲染的 link 全部 active

配置 props

配置

//props写法1,key-value以props形式传给Msg,传递固定数据,很少用
props: { a: 1, b: "hello" },
//props写法2,值为布尔值,若为真,就会把该路由组件收到的所有params参数以props参数传给组件Msg,但不会理会query参数
props: true,
//props写法3,值为函数,把所有query参数传递给Msg,用解构更简洁,个人感觉作用鸡肋
props({ query: { id, item } }) {
 return { id, item };
},

使用

<template>
  <div>
    <h2>{{ id }} {{ item }}</h2>
  </div>
</template>

<script>
export default {
  name: "a-msg",
  mounted() {
    console.log(this.$route);
  },
  computed: {},
  props: ["id", "item"],
};
</script>

<style>
</style>

router-link replace

作用:控制路由跳转时操作浏览器历史记录的模式

浏览器的历史记录有两种写入方式,分别为 push 和 replace。push 是追加记录(默认),可以按步骤一步步后退;replace 是替换当前记录,后退时不再一步步后退,而是回退到上一个 push 内容里

开启 replace 模式,在 router-link 标签内添加replace 或者:replace:"true"

编程式路由跳转

不借助 router-link 实现路由跳转

 pushShow() {
      this.$router.push({
        name: "msg",
        params: {
          id: xxx,
          item: xxx,
        },
      });
    },
replaceShow() {
      this.$router.replace({
        name: "msg",
        params: {
          id: xxx,
          item: xxx,
        },
      });
    },
forward() {
      this.$router.forward();
    },
back() {
      this.$router.back();
    },
refresh() {
      this.$router.go(0);
    },

keep-alive

让 router-view 切换时做缓存,不销毁切换出去的页面

<keep-alive include="">
      <router-view></router-view>
    </keep-alive>

include 不写就是全缓存,如果需要指定缓存组件,则写入组件名或组件名数组

路由守卫

全局守卫

const router = new VueRouter({
  routes: [
    {
      name: "about",
      path: "/about",
      component: About,
      meta: {
        title: "关于",
        isAuth:true
      },
    },
    ...
  ],
});
//全局前置路由守卫——初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to, from, next) => {
  console.log(to, from);
  //to.path === "/home/ia" || to.path === "/home/ib"
  if (to.meta.isAuth) { //鉴权
    if (localStorage.getItem("keyword") === "haian") {
      next();
    } else {
      console.log(localStorage.getItem("keyword"));
      alert("not haian");
    }
  } else {
    next();
  }
});
//全局后置路由守卫——初始化时执行、每次路由切换后执行
router.afterEach((to, from) => {
  console.log(to, from);
  document.title = to.meta.title;
});

export default router;

独享路由守卫

{
          name: "innera",
          path: "ia",
          component: InnerA,
          meta: {
            isAuth: true,
            title: "内页 A",
          },
          beforeEnter: (to, from, next) => {
            console.log(to,from)
            if (localStorage.getItem("keyword") === "haian") {
              next();
            } else {
              console.log(localStorage.getItem("keyword"));
              alert("not haian");
            }
          },
          children: [
            {
              ...
            },
          ],
        },

在路由配置加beforeEnter,用法同全局路由守卫,但是独享路由守卫没有后置的

组件内守卫

export default {
  name: "a-Home",
  beforeRouteEnter(to, from, next) {
    // 通过路由规则,进入该组件时被调用
    console.log(to, from);
    if (localStorage.getItem("keyword") === "haian") {
      next();
    } else {
      console.log(localStorage.getItem("keyword"));
      alert("not haian");
    }
  },
  beforeRouteLeave(to, from, next) {
    // 通过路由规则,离开该组件时被调用
    console.log(to, from, next);
    alert("goodbye ~");
    next();
  },
};
</script>

注意,这两个钩子只有根据路由规则进入、离开时才会被调用

history 与 hash 模式

关于 hash

默认模式为 hash,对一个 url 来说,hash 就是#及其后面的值。

hash 值不会包含在 http 请求中,hash 值不会带给服务器

开启 history 模式

const router = new VueRouter({
  mode:'history',
  routes: []
...

区别

hash 模式:

  • 地址中永远带着#,不美观
  • 若以后将地址通过第三方手机 app 分享,若 app 校验严格,则地址会标记为不合法
  • 兼容性较好

history 模式:

  • 地址干净美观
  • 兼容性略差
  • 应用部署上线时,需要后端人员支持,解决刷新页面 404 问题
Last Modified: July 10, 2022