系统性学习vue-vue-router

路由的简介

vue-router的一个插件库,专门用来实现SPA应用

SPA

SPA(single page web application)单页面web应用
SPA整个应用只有一个完整的页面
SPA点击页面中的导航链接不会刷新页面,只会做页面的局部更新,数据需要通过ajax请求获取

路由

一个路由就是一组映射关系(key-value)
key为路径,value可能是function或component
有前端路由也有后端路由:前端路由-key对应组件;后端路由-key对应函数

观察下面动图,前面点击文档和API时页面并没有刷新且页面头部并没有变化,只是路径和页面下部发生了变化,而点击“演练场”时直接跳转到另一个页面了
在这里插入图片描述

路由的基本使用

安装

注意:目前vue-router最新版本是4,只支持vue3;当前使用的是vue2所以要下2版本的
npm i vue-router@3

引入

//main.js
import VueRouter from "vue-router";
//...
Vue.use(VueRouter);

引入完成后,我们就可以在创建Vue中传入router配置项
首先创建router文件
在这里插入图片描述
配置上了两个路由
About和Home是两个路由组件

// router/index.js
// 该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
import Vue from "vue";

// 引入组件
import About from "../components/About";
import Home from "../components/Home";

Vue.use(VueRouter);

// 创建并暴露一个路由器
export default new VueRouter({
  // 配置路由
  routes: [
    {
      path: "/about",
      component: About,
    },
    {
      path: "/home",
      component: Home,
    },
  ],
});

然后在vue实例中配置(感觉和vuex一样一样的)

new Vue({
  render: (h) => h(App), //将App组件放入容器中
  // ...
  router,
  //...
}).$mount("#app"); //绑定模板

看浏览器中路径,有个#说明配置成功了
在这里插入图片描述

使用

标签式

在组件中使用<router-link>标签,其实解析后就是<a>标签
to是跳转路由path,activeClass是激活状态class

<div class="row">
  <router-link to="/about" active-class="active">About</router-link>
  <router-link to="/home" active-class="active">Home</router-link>
</div>

而组件展示的位置用<router-view>

<!-- 指定组件呈现位置 -->
<router-view></router-view>

运行结果
在这里插入图片描述

编程式

还有一种编程式路由之后讲

注意

  • 上面的Home和About是路由组件
    而之前使用的是一般组件,用<>标签引用
    所以为了区分这两个组件,一般要在components平级创建一个pages文件夹存放路由组件
    在这里插入图片描述
  • 当一个路由组件不需要显示时,会直接将组件销毁,需要显示时再次挂载
  • 我们将路由组件输出,可以看到多出来两个东西
    $route是每个路由组件都有的专属属性,存储着自己的路由信息
    $router是整个应用的路由器,只有一个,来管理路由
    在这里插入图片描述

嵌套(多级)路由

路由套路由
如下在Home下再添加两个路由
注意:子路由的path不要写成"/home/news"或者"/news"router会给拼好的

// 创建并暴露一个路由器
export default new VueRouter({
  // 配置路由
  //   一级路由
  routes: [
    {
      path: "/about",
      component: About,
    },
    {
      path: "/home",
      component: Home,
      // 二级路由
      children: [
        {
          path: "news",
          component: News,
        },
        {
          path: "message",
          component: Message,
        },
      ],
    },
  ],
});

使用时to要写全<router-link to="/home/news" active-class="active">Home/News</router-link>

路由传参

query参数

传递参数,两种写法

<!-- 跳转路由并携带query参数,to的字符串写法 -->
<router-link :to="`/home?id=${id}i&name=${name}`" active-class="active">Home</router-link>
<!-- 跳转路由并携带query参数,to的对象写法 -->
<router-link
  :to="{
    path: '/home',
    query: {
      id,
      name,
    },
  }"
  active-class="active"
  >Home</router-link
>

接收参数

<h2>我是Home内容:Hello {{ $route.query.name }}</h2>

params参数

配置路由的地方也要修改,要写上需要传的参数

{
  path: "/home/:id/:name", //使用占位符声明接收params参数
  // path: "/home",
  component: Home,
  // ...
},
<!-- 跳转路由并携带params参数,to的字符串写法 -->
<router-link :to="`/home/${id}/${name}`" active-class="active"
  >Home</router-link
>

对象写法需要注意的是必须要用name指定路由,不可以用路径path(是一个坑)

<router-link
  :to="{
    name: 'home',
    params: {
      id,
      name,
    },
  }"
  >Home</router-link
>

接收参数

<h2>我是Home内容:Hello {{ $route.params.name }}</h2>

命名路由

就是在路由配置项中添加个name

//...
{
  name: "detail",
  path: "/detail",
  component: Detail,
},
//...

作用就是可以简化路由跳转编码

<router-link to="/home/news/detail" active-class="active"
  >Detail</router-link
>
<!-- 简化为↓ -->
<router-link :to="{ name: 'detail' }" active-class="active"
  >Detail</router-link
>

路由的props配置

接收路由参数展示时<h2>我是Home内容:Hello {{ $route.params.name }}</h2>
会不会觉的获取的比较繁琐
这里就要使用props了
需要先在路由上配置

{
   name: "home",
   path: "/home/:id/:name", //传递params参数
   // path: "/home",
   component: Home,
   // props的第一种写法,值为对象,对对象中的所有key-value都会以props的形式传给对应的组件
   // props: { a: 1, b: 333 }, // 但是不推荐,因为只能写死数据
   // props的第二种写法,值为布尔,若为真就会把该路由组件收到的所有params参数,以props的形式传给Detail组件
   // props: true, //只能与params配合使用
   // props的第三种写法,值为函数
   props($router) {
     return { id: $router.query.id, name: $router.query.name };
   },
   // 或者用结构赋值简写
   //  props({query:{id,name}}) {
  //  return { id,name };
  // },
  //...
}

在组件上用props接收使用(就是父组件传参那样)

props: ["id", "name"],
<h2>我是Home内容:Hello {{ name }}</h2>

router-link的replace属性

每一次点击router-link默认都会将历史记录push到一个栈中,指针指向当前展示的页面
每次点击浏览器的后退键,就会让指针指向上一个记录页面也会变成上一个记录的样式
在这里插入图片描述
而可以通过配置将push模式改为replace模式
即每次跳转都会覆盖前一个历史记录
在router-link加个replace属性就可以了

<router-link replace to="/about" active-class="active">About</router-link>

编程式路由导航

路由跳转

<button @click="toHome">点击跳转Home组件</button>
toHome() {
  this.$router.push({
    name: "home",
    params: {
      id: this.id,
      name: this.name,
    },
  });
},

当然也能用replace,push改为replace就行

后退和前进

back() {
  // 后退
  // this.$router.back();
  // 后退多步
  this.$router.go(-2);
},
forward() {
  // 前进
  this.$router.forward();
  // 前进多步
  // this.$router.go(2);
},

缓存路由组件

之前知识点:路由组件不显示默认是会销毁掉,再次显示时再重新挂载
但有时我们需要对页面上的数据进行缓存
就可以用<keep-alive>标签包裹路由组件显示位置,可以添加include来配置想缓存的组件名称(这里注意要记得在组件里配置name)
如下代码就是要将Home组件内容进行缓存,而About不进行缓存

<keep-alive include="Home">
  <!-- 指定组件呈现位置 -->
  <router-view></router-view>
</keep-alive>

效果如下
在这里插入图片描述
缓存多个组件,应该猜到了

<keep-alive :include="['Home','About']">

两个新的生命周期钩子函数

想象一个场景(懒得写实例了)
两个路由组件可以来回切换,且都为缓存路由组件,
第一个组件上在mounted设置了一个定时器setInterval实现透明渐变效果,并在beforeDestory里销毁的定时器clearInterval
从第一个路由组件切换到第二个路由组件后,会发现定时器并没有被销毁,一直在执行,是因为组件并没有被销毁,这并不是我们想得到的
咋整?
引出两个路由组件独有的生命周期钩子激活:activated失活:deactivated (就是onShow和onHide)

tips:之前声明周期图中有三个钩子函数没有写在上面,激活和失活,还有一个就是nextTick

路由守卫

就是切换路由组件时进行操作
需要再touter/index.js中配置

全局前置守卫

当需要在跳转前检查权限等操作,无权限则不跳转,就需要用到前置路由守卫
首先不能先直接暴露,要在最后暴露
通过beforeEach钩子函数来控制放行,next是用来放行,不写就不会跳转

//...
const router = new VueRouter({
//...
})
// 全局前置路由守卫 初始化以及每次路由切换前调用
// to-前往的路由信息 from-来自的路由信息 next-放行
router.beforeEach((to, from, next) => {
  console.log("to:", to);
  console.log("from:", from);
  next();
});

export default router;

在这里插入图片描述
就可以在beforeEach中根据条件和目的信息等来判断是否放行

还有个问题是当我们需要检查权限的页面很多时,那判断语句就会很长,
优化方法是使用路由中的一个配置项:meta元信息-用于添加一些自定义的数据

{
  name: "about",
  path: "/about",
  component: About,
  meta: {
    isAuth: true,
  },
},

这样在beforeEach中判断,直接用if (to.meta.isAuth){//权限判断}

全局后置守卫

当我们需要再路由正确切换后再进行一些操作时,就用后置路由守卫
比如修改页面标题在这里插入图片描述首先要在每个需要配置的路由的meta中添加title属性

{
  name: "about",
  path: "/about",
  component: About,
  meta: {
    isAuth: true,
    title: "关于",
  },
},

在后置路由守卫中修改title

// 全局后置路由守卫 初始化以及每次路由切换后调用
// to-前往的路由信息 from-来自的路由信息
router.afterEach((to, from) => {
  document.title = to.meta.title || "我的页面";
});

有可能会遇到切换路由时,页面标题闪现数项目名称,是因为在index.html中我们配置的title就是项目名称,改为默认名称就可以了

<!--index.html-->
<!-- <title><%= htmlWebpackPlugin.options.title %></title> -->
<title>我的页面</title>

独享路由守卫

只对某一个路由进行操作

{
  name: "about",
  path: "/about",
  component: About,
  meta: {
    isAuth: true,
    title: "关于",
  },
  // 独享路由守卫 当跳转进入当前路由之前调用
  beforeEnter: (to, from, next) => {
    // ...
  }
},

没有afterEnter

组件内路由守卫

在对应路由组件中配置的

// About.vue
// 进入守卫 通过路由规则,进入该组件时被调用
beforeRouteEnter(to, from, next) {
  // ...
},
// 离开守卫 通过路由规则,离开该组件时被调用
beforeRouteLeave(to, from, next) {
  // ...
},

history模式和hash模式

路由有两种工作模式:history模式和hash模式
默认是hash模式
可以通过mode来修改模式

const router = new VueRouter({
  // 配置路由
  mode: "history",
  //...
})

两者区别就是

hash模式
url中#及其后面的内容是hash值,hash值不会包含在http请求中,即:hash值不会带给服务器
优缺点:

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

在这里插入图片描述

history模式
优缺点:

  • 地址干净,美观
  • 兼容性和hash模式相比略差
  • 应用部署上线时需要后端人员支持,解决刷新页面服务端404问题

在这里插入图片描述

element-ui基本使用

移动端常用UI组件库:

PC端常用UI组件库

当使用Element-UI时,按照官网写完整引入,会将所有的组件及样式都引入进来以方便直接使用,就会导致最后包体很大
所以需要按需引入,官网下面就有,看去吧
需要注意的几点:

  1. .babelrc文件就是babel.config.js
  2. 原始的配置不要删掉,要追加
  3. 报错Plugin/Preset files are not allowed to ...["es2015", { "modules": false }]应该改为["@babel/preset-env", { "modules": false }]

下一篇:系统性学习vue-vue3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值