Vue2:路由2

简介: Vue2:路由2

path路径跳转传参

传参:


两种跳转方式,对于两种传参方式都支持:① path 路径跳转传参 ② name 命名路由跳转传参


**path路径跳转传参(query传参):

//简单写法
this.$router.push('/路径?参数名1=参数值1&参数2=参数值2')
//完整写法
this.$router.push({
  path: '/路径',
  query: {
    参数名1: '参数值1',
    参数名2: '参数值2'
  }
})

接受参数的方式依然是:$route.query.参数名


举例:


Home.vue

goSearch() {
  this.$router.push({
    path: '/search',
    query: {
      p1: this.inpValue,
    }
  })
}

Search.vue

<p>搜索关键字: {{ $route.query.p1 }}</p>

**path路径跳转传参(动态路由传参):


index.js 先在index中写出动态路由

{ path: '/search/:words', component: Search },

Home.vue

//简单写法
this.$router.push('/路径/参数值')
//完整写法
this.$router.push({
  path: '/路径/参数值'
})

Search.vue 接受参数的方式依然是:$route.params.参数值

<p>搜索关键字: {{ $route.params.words }}</p>

**注意:**path不能配合params使用


name命名路由传参

1.name 命名路由跳转传参 (query传参)

this.$router.push({
  name: '路由名字',
  query: {
    参数名1: '参数值1',
    参数名2: '参数值2'
  }
})

案例:


index.js

{ name: 'test', path: '/search', component: Search}

Home.vue

goSearch() {
  this.$router.push({
    name: 'test',
    query: {
      key: this.inpValue
    }
  })
}

Search.vue

<p>搜索关键字: {{ $route.query.key }}</p>

2.name 命名路由跳转传参 (动态路由传参)

this.$router.push({
  name: '路由名字',
  params: {
    参数名: '参数值',
  }
})

案例:


index.js

{ name: 'test', path: '/search/:words', component: Search}

Home.vue

goSearch() {
  this.$router.push({
    name: 'test',
    params: {
      words: this.inpValue
    }
  })
}

Search.vue

<p>搜索关键字: {{ $route.params.words }}</p>

总结

编程式导航,如何跳转传参?


1.path路径跳转

—query传

this.$router.push('/路径?参数名1=参数值1&参数2=参数值2')
this.$router.push({
  path: '/路径',
  query: {
    参数名1: '参数值1',
    参数名2: '参数值2'
  }
})

—动态路由传参

this.$router.push('/路径/参数值')
this.$router.push({
  path: '/路径/参数值'
})


query与动态路由的区别:前者适合传多个参数,后者适合传入单个参数


2.name命名路由跳转


query传参

this.$router.push({
  name: '路由名字',
  query: {
    参数名1: '参数值1',
    参数名2: '参数值2'
  }
})

动态路由传参 (需要配动态路由)

this.$router.push({
  name: '路由名字',
  params: {
    参数名: '参数值',
  }
})

path路径跳转和name命名路由跳转区别:前者简易方便,后者适合path路径长的场景


面经基础版本-案例效果分析

效果与功能分析:

面经效果演示

a3a753a1ccba704361693eac6e69c4ca.png

功能分析


1-配路由


首页 和 面经 详情,两个一级路由


首页内嵌四个可切换页面(嵌套二级路由)


2-实现功能


首页请求渲染


跳转传参 到 详情页,详情页渲染


组件缓存,优化性能

098161c4f18087bf781f64f950a8792b.png

一级路由配置:

1.把文档中准备的素材拷贝到项目中


2.针对router/index.js文件 进行一级路由配置

...
import Layout from '@/views/Layout.vue'
import ArticleDetail from '@/views/ArticleDetail.vue'
...
const router = new VueRouter({
  routes: [
    {
      path: '/',
      component: Layout
    },
    {
      path: '/detail',
      component: ArticleDetail
    }
  ]
})

二级路由配置

二级路由也叫嵌套路由,当然也可以嵌套三级、四级…


1.使用场景


当在页面中点击链接跳转,只是部分内容切换时,我们可以使用嵌套路由


2.语法

在一级路由下,配置children属性即可

配置二级路由的出口


1.在一级路由下,配置children属性


注意:一级的路由path 需要加 /

const router = new VueRouter({
  routes: [
    {
      path: '/',
      component: Layout,
      children:[
        //children中的配置项 跟一级路由中的配置项一模一样 
        {path:'xxxx',component:xxxx.vue},
        {path:'xxxx',component:xxxx.vue},
      ]
    }
  ]
})

技巧:二级路由应该配置到哪个一级路由下呢?


这些二级路由对应的组件渲染到哪个一级路由下,children就配置到哪个路由下边

2.配置二级路由的出口


注意: 配置了嵌套路由,一定配置对应的路由出口,否则不会渲染出对应的组件


Layout.vue

<template>
  <div class="h5-wrapper">
    <div class="content">
      <router-view></router-view>
    </div>
  ....
  </div>
</template>

Code:


index.js

import Vue from 'vue'
import VueRouter from "vue-router";
import Layout from '@/views/Layout'
import Article from '@/views/Article'
import Collect from '@/views/Collect'
import Like from '@/views/Like'
import User from '@/views/User'
import ArticleDetail from '@/views/ArticleDetail'
Vue.use(VueRouter)
const router = new VueRouter({
  // article 路径 -> Article 组件
  // 通过 children 配置项,可以配置嵌套路由
  // 1. 在 children 配置项中,配规则
  // 2. 准备二级路由出口
  routes: [
    {
      path: '/',
      component: Layout,
      children: [
        {
          path: '/article',
          component: Article,
        },
        {
          path: '/collect',
          component: Collect,
        },
        {
          path: '/like',
          component: Like,
        },
        {
          path: '/user',
          component: User,
        },
      ]
    },
    {
      path: '/detail',
      component: ArticleDetail
    }
  ]
})
export default router

Layout.vie

<template>
  <div class="h5-wrapper">
    <div class="content">
      <!-- 二级路由出口,匹配到的二级路由组件就会展示 -->
      <router-view></router-view>
    </div>
    <nav class="tabbar">
      <a href="#/article">面经</a>
      <a href="#/collect">收藏</a>
      <a href="#/like">喜欢</a>
      <a href="#/user">我的</a>
    </nav>
  </div>
</template>
<script>
export default {
  name: "LayoutPage",
}
</script>
<style>
body {
  margin: 0;
  padding: 0;
}
</style>
<style lang="less" scoped>
.h5-wrapper {
  .content {
    margin-bottom: 51px;
  }
  .tabbar {
    position: fixed;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 50px;
    line-height: 50px;
    text-align: center;
    display: flex;
    background: #fff;
    border-top: 1px solid #e4e4e4;
    a {
      flex: 1;
      text-decoration: none;
      font-size: 14px;
      color: #333;
      -webkit-tap-highlight-color: transparent;
    }
  }
}
</style>

二级导航高亮

实现思路

将a标签替换成 组件,配置to属性,不用加 #

结合高亮类名实现高亮效果 (推荐模糊匹配:router-link-active)


代码实现


Layout.vue

<nav class="tabbar">
  <router-link to="/article">面经</router-link>
  <router-link to="/collect">收藏</router-link>
  <router-link to="/like">喜欢</router-link>
  <router-link to="/user">我的</router-link>
</nav>
---------------------------
a.router-link-active {
  color: orange
}

Code:

<template>
  <div class="h5-wrapper">
    <div class="content">
      <!-- 二级路由出口,匹配到的二级路由组件就会展示 -->
      <router-view></router-view>
    </div>
    <nav class="tabbar">
      <router-link to="/article">面经</router-link>
      <router-link to="/collect">收藏</router-link>
      <router-link to="/like">喜欢</router-link>
      <router-link to="/user">我的</router-link>
    </nav>
  </div>
</template>
<script>
export default {
  name: "LayoutPage",
}
</script>
<style>
body {
  margin: 0;
  padding: 0;
}
</style>
<style lang="less" scoped>
.h5-wrapper {
  .content {
    margin-bottom: 51px;
  }
  .tabbar {
    position: fixed;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 50px;
    line-height: 50px;
    text-align: center;
    display: flex;
    background: #fff;
    border-top: 1px solid #e4e4e4;
    a {
      flex: 1;
      text-decoration: none;
      font-size: 14px;
      color: #333;
      -webkit-tap-highlight-color: transparent;
    }
    a.router-link-active {
      color: orange
    }
  }
}
</style>

首页请求渲染

1.步骤分析


1.安装axios


2.看接口文档,确认请求方式,请求地址,请求参数


3.created中发送请求,获取数据,存储到data中


4.页面动态渲染


2.代码实现


1.安装axios

yarn add axios  npm i axios

2.接口文档

请求地址: https://mock.boxuegu.com/mock/3083/articles
请求方式: get

3.created中发送请求,获取数据,存储到data中

data() {
  return {
    articelList: [],
  }
},
async created() {
  const {  data: { result: { rows } }} = await axios.get('https://mock.boxuegu.com/mock/3083/articles')
  this.articelList = rows
},

4.页面动态渲染

<template>
  <div class="article-page">
    <div class="article-item" v-for="item in articelList" :key="item.id">
      <div class="head">
        <img :src="item.creatorAvatar" alt="" />
        <div class="con">
          <p class="title">{{ item.stem }}</p>
          <p class="other">{{ item.creatorName }} | {{ item.createdAt }}</p>
        </div>
      </div>
      <div class="body">
        {{item.content}}
      </div>
      <div class="foot">点赞 {{item.likeCount}} | 浏览 {{item.views}}</div>
    </div>
  </div>
</template>

查询参数传参

1.说明


跳转详情页需要把当前点击的文章id传给详情页,获取数据


查询参数传参 this.$router.push(‘/detail?参数1=参数值&参数2=参数值’)

动态路由传参 先改造路由 在传参 this.$router.push(‘/detail/参数值’)


2.查询参数传参实现

关键点:


1-点击跳转文章详情


Article.vue

@click="$router.push(`/detail?id=${item.id}`)"

2-实现返回上一级:采用 $router.back()

ac646a65580eebca84e8e0bac2d9e564.png

ArticleDetail.vue

<nav class="nav"><span @click="$router.back()" class="back">&lt;</span> 面经详情</nav>

动态路由传参

1.实现步骤

改造路由

动态传参

在详情页获取参数

2.代码实现

改造路由


router/index.js


3.额外优化功能点-点击回退跳转到上一页


详情页渲染

1.实现步骤分析

导入axios

查看接口文档

在created中发送请求

页面动态渲染


2.代码实现


接口文档

请求地址: https://mock.boxuegu.com/mock/3083/articles/:id
请求方式: get

这里id走的是动态参数


关键:


优化空白界面:

142e6ba64081ecafd7e826ac780af35b.png

问题:在跳转页面的过程中,有空白浏览量和点赞等空白界面


原理:在请求和响应中间,不让template先去加载空的article对象


解决方案:


在 article.id 存在之后,再去做页面渲染

<div class="article-detail-page" v-if="article.id">
-----------------------------------------------------
data() {
  return {
    article: {},
  }
},

Code:


ArticleDetail.vue

<template>
  <div class="article-detail-page" v-if="article.id">
    <nav class="nav"><span @click="$router.back()" class="back">&lt;</span> 面经详情</nav>
    <header class="header">
      <h1>{{ this.article.stem }}</h1>
      <p>{{ this.article.createdAt }} | {{ this.article.views }} 浏览量 | {{ this.article.likeCount }} 点赞数</p>
      <p>
        <img
          :src=this.article.creatorAvatar
          alt=""
        />
        <span>{{ this.article.creatorName }}</span>
      </p>
    </header>
    <main class="body">
      {{ this.article.content }}
    </main>
  </div>
</template>
<script>
import axios from 'axios'
// 请求地址: https://mock.boxuegu.com/mock/3083/articles/:id
// 请求方式: get
export default {
  name: "ArticleDetailPage",
  data() {
    return {
      article: {},
    }
  },
  async created() {
    const id = this.$route.query.id
    const { data } = await axios.get(`https://mock.boxuegu.com/mock/3083/articles/${id}`)
    // console.log(data);
    this.article = data.result
  },
}
</script>
<style lang="less" scoped>
.article-detail-page {
  .nav {
    height: 44px;
    border-bottom: 1px solid #e4e4e4;
    line-height: 44px;
    text-align: center;
    .back {
      font-size: 18px;
      color: #666;
      position: absolute;
      left: 10px;
      top: 0;
      transform: scale(1, 1.5);
    }
  }
  .header {
    padding: 0 15px;
    p {
      color: #999;
      font-size: 12px;
      display: flex;
      align-items: center;
    }
    img {
      width: 40px;
      height: 40px;
      border-radius: 50%;
      overflow: hidden;
    }
  }
  .body {
    padding: 0 15px;
  }
}
</style>

缓存组件

问题:


从面经列表 点到 详情页,又点返回,数据重新加载了 → 希望回到原来的位置

原因:


当路由被跳转后,原来所看到的组件就被销毁了(会执行组件内的beforeDestroy和destroyed生命周期钩子),重新返回后组件又被重新创建了(会执行组件内的beforeCreate,created,beforeMount,Mounted生命周期钩子),所以数据被加载了


**解决方案:**利用keep-alive把原来的组件给缓存下来


keep-alive


概念:它是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。


keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件中。


优点:


在组件切换过程中把切换出去的组件保留在内存中,防止重复渲染DOM,


减少加载时间及性能消耗,提高用户体验性。


keep-alive的三个属性


① include : 组件名数组,只有匹配的组件会被缓存


② exclude : 组件名数组,任何匹配的组件都不会被缓存


③ max : 最多可以缓存多少组件实例


案例:


对Layout页面进行缓存

842d54b50d27df33e18bbc0ffc114a0f.png

如右边红框所示,当我们拉到这个位置时,再点击‘前端小白’这篇文章,然后退回来,会发现拖动条仍然在这个位置。

394c6c59657e7ba0454467fd0c66c27b.png

原理:被缓存的组件会多两个生命周期


额外的两个生命周期钩子:keep-alive的使用会触发两个生命周期函数


activated 当组件被激活(使用)的时候触发 → 进入这个页面的时候触发


deactivated 当组件不被使用的时候触发 → 离开这个页面的时候触发


组件缓存后就不会执行组件的created, mounted, destroyed 等钩子了


所以其提供了actived 和deactived钩子,帮我们实现业务需求。


理解:


如下图所示:当我们为 Layout 组件的生命周期钩子绑定输出函数,但是他们只会执行一次,之后尽管我们切换页面到 ArticleDetail 中再切回去,也不会再触发生命周期函数。

82f0f2071b5be495ce66e69a11d19f07.png

为了弥补无法使用之前生命函数的问题,Vue提供了 activated 和 deactivated 两个函数


如图,当我们第一次加载页面时,就会有 created mounted activated 三个函数被触发

28f49c295c70573e5690caa0011aab09.png

当我们切换到 ArticleDetail 时,就会触发deactivated函数

df13bedf7d50b7e661abd93c0787ab47.png

总结:


1.keep-alive是什么

vue 的内置组件,包裹动态组件时,可以缓存

2.keep-alive的优点

组件切换过程中 把切换出去的组件保留在内存中(提升性能)

3.keep-alive的三个属性(了解)

  1-include:组件名数组,只有匹配的组件会被缓存

  2-exclude :组件名数组,任何匹配的组件都不会被缓存

  3-max:最多可以缓存多少组件实例

4.keep-alive的使用会触发两个生命周期函数(了解)

activated 当组件被激活(使用)的时候触发 → 进入页面触发

deactivated 当组件不被使用的时候触发 → 离开页面触发


面经总结:

311dc0477afb9d1c1d632c656b5e1d96.png

vue-router 的高级用法(参考21版Vue)

路由重定向

路由重定向指的是:用户在访问地址 A 的时候,强制用户跳转到地址 C ,从而展示特定的组件页面。通过路由规则的 redirect 属性,指定一个新的路由地址,可以很方便地设置路由的重定向:

const router = createRouter({
  // 3.1 通过 history 属性指定路由的工作模式
  history: createWebHashHistory(),
  // 3.2 通过 routes 数组,指定路由规则
  routes: [
    // path 是 hash 地址, component 是要展示的组件
    { path: '/', redirect: '/home' },
    { path: '/home', component: MyHome },
    { path: '/movie', component: MyMovie },
    { path: '/about', component: MyAbout },
  ]
})

路由高亮

可以通过如下的两种方式,将激活的路由链接进行高亮显示:


① 使用默认的高亮 class 类 ② 自定义路由高亮的 class 类


2.1 默认的高亮 class 类

被激活的路由链接,默认会应用一个叫做 router-link-active 的类名。开发者可以使用此类名选择器,为激活的路由链接设置高亮的样式:

/* 在 index.css 全局样式表中,重新 router-link-active 的样式 */
.router-link-active {
  background-color: red;
  color: white;
  font-weight: bold;
}

效果:

880aebb0bdb2fb9768fde7a07b44dd67.png

2.2 自定义路由高亮的 class 类

在创建路由的实例对象时,开发者可以基于 linkActiveClass 属性,自定义路由链接被激活时所应用的类名:

// 3. 创建路由实例对象
const router = createRouter({
  // 3.1 通过 history 属性指定路由的工作模式
  history: createWebHashHistory(),
  // 指定被激活的路由链接,会应用 router-active 这个类名
  // 默认的 router-link-active 类名会被覆盖掉
  linkActiveClass: 'router-active',
  // 3.2 通过 routes 数组,指定路由规则
  routes: [
    // 其中,path 表示需要被重定向的“原地址”,redirect表示将要被重定向到的“新地址”
    { path: '/', redirect: '/movie' },
    // path 是 hash 地址, component 是要展示的组件
    { path: '/home', component: MyHome },
    { path: '/movie', component: MyMovie },
    { path: '/about', component: MyAbout },
  ]
})

嵌套路由

通过路由实现组件的嵌套展示,叫做嵌套路由。

236950f1472864901309c9addcae3efe.png

① 声明子路由链接和子路由占位符


② 在父路由规则中,通过 children 属性嵌套声明子路由规则


3.1 声明子路由链接和子路由占位符

在 About.vue 组件中,声明 tab1 和 tab2 的子路由链接以及子路由占位符。示例代码如下:

<template>
  <div>
    <h1>MyApp</h1>
    <!-- 在关于页面中,声明两个子路由链接 -->
    <router-link to="/about/tab1">Tab1</router-link>&nbsp;
    <router-link to="/about/tab2">Tab2</router-link>&nbsp;
    <router-link to="/about/tab3">Tab3</router-link>
    <hr />
    <!-- 在关于页面中,声明 tab1 和 tab2 的路由占位符 -->
    <router-view></router-view>
  </div>
</template>

3.2 通过 children 属性声明子路由规则


在 router.js 路由模块中,导入需要的组件,并使用 children 属性声明子路由规则。示例代码如下:

import Tab1 from './tabs/MyTab1.vue'
import Tab2 from './tabs/MyTab2.vue'
// 创建路由对象
const router = createRouter({
  // 指定路由的工作模式
  history: createWebHashHistory(),
  // 自定义路由高亮的 class 类
  linkActiveClass: 'active-router',
  // 声明路由的匹配规则
  routes: [
    { path: '/', redirect: '/home'},
    { path: '/home', component: Home },
    { path: '/movie', component: Movie },
    { path: '/about', component: About, children: [
      // 通过 children 属性嵌套子级路由规则
      { path: 'tab1', component: Tab1 }, // 访问 /about/tab1 时, 展示 Tab1 组件
      { path: 'tab2', component: Tab2 }, // 访问 /about/tab2 时,展示 Tab2 组件
    ] },
  ]
})

注意:子路由规则的 path 不要以 / 开头!


3.3 子路由重定向


当我们点击‘关于’时,可以直接显示出Tab1中的内容:

921c1e655f7ac47f8da8b63fd4ba406a.png

routes: [
  // 其中,path 表示需要被重定向的“原地址”,redirect表示将要被重定向到的“新地址”
  { path: '/', redirect: '/movie' },
  // path 是 hash 地址, component 是要展示的组件
  { path: '/home', component: MyHome },
  { path: '/movie', component: MyMovie },
  { path: '/about', component: MyAbout , redirect: '/about/tab1',children: [
    { path: 'tab1', component: Tab1 },
    { path: 'tab2', component: Tab2 },
  ]},
]

动态路由匹配

思考:有如下 3 个路由链接:

<router-link to="/movie/1">电影1</router-link>&nbsp;
<router-link to="/movie/2">电影2</router-link>&nbsp;
<router-link to="/movie/3">电影3</router-link>&nbsp;

定义如下 3 个路由规则,是否可行???

{ path: '/movie/1', component: Movie },
{ path: '/movie/2', component: Movie },
{ path: '/movie/3', component: Movie },

缺点:路由规则的复用性差。


4.1 动态路由的概念


动态路由指的是:把 Hash 地址中可变的部分定义为参数项,从而提高路由规则的复用性。在 vue-router 中使用英文的冒号(:)来定义路由的参数项。


示例代码如下:

// 路由中的动态参数以:进行声明,冒号后面的是动态参数的名称
{ path: '/movie/:id', component: Movie },
// 将以下3个路由规划,合并成了一个,提高了路由规划的复用性
{ path: '/movie/1', component: Movie }
{ path: '/movie/2', component: Movie }
{ path: '/movie/3', component: Movie }

4.2 $route.params 参数对象


通过动态路由匹配的方式渲染出来的组件中,可以使用 $route.params 对象访问到动态匹配的参数值。

<template>
  <!-- $route.params 是路由的“参数对象” -->
  <h3>MyMoive --- {{ $route.params.id }}</h3>
</template>
<script>
export default {
  name: 'MyMovie'
}
</script>

4.3 使用 props 接收路由参数

为了简化路由参数的获取形式,vue-router 允许在路由规则中开启 props 传参。示例代码如下:

// 在定义路由规则时,声明 props: true 选项
    // 即可在 Movie 组件中,以 props 的形式接收到路由规则匹配到的参数项
{ path: '/movie/:id', component: MyMovie , props: true},
<template>
  <!-- 3.直接使用 props 中接收路由参数 -->
  <h3>MyMoive --- {{ id }}</h3>
</template>
<script>
export default {
  name: 'MyMovie',
  props: ['id'] // 2. 使用 props 接收路由规则中匹配到的参数项
}
</script>

编程式导航

通过调用 API 实现导航的方式,叫做编程式导航。与之对应的,通过点击链接实现导航的方式,叫做声明式导航。例如:


普通网页中点击链接、vue 项目中点击 都属于声明式导航


普通网页中调用 location.href 跳转到新页面的方式,属于编程式导航


5.1 vue-router 中的编程式导航 API


vue-router 提供了许多编程式导航的 API,其中最常用的两个 API 分别是:


① this.$router.push(‘hash 地址’)


跳转到指定 Hash 地址,从而展示对应的组件


② this.$router.go(数值 n)


实现导航历史的前进、后退


**5.2 r o u t e r . p u s h ∗ ∗ 调用 t h i s . router.push** 调用 this.router.push∗∗调用this.router.push() 方法,可以跳转到指定的 hash 地址,从而展示对应的组件页面。示例代码如下:

<template>
  <h3>MyHome</h3>
  <button @click="goToMovie(3)">导航到Movie页面</button>
</template>
<script>
export default {
  name: 'MyHome',
  methods: {
    goToMovie(id) {
      this.$router.push('/movie/' + id)
      // this.$router.push(`/movie/${id}`)
    }
  }
}
</script>

5.2 $router.go


调用 this.$router.go() 方法,可以在浏览历史中进行前进和后退。示例代码如下:

<template>
  <!-- 3.直接使用 props 中接收路由参数 -->
  <h3>MyMoive --- {{ id }}</h3>
  <button @click="goBack()">回上一个</button>
</template>
<script>
export default {
  name: 'MyMovie' ,
  props: ['id'] ,// 2. 使用 props 接收路由规则中匹配到的参数项
  methods: {
    goBack() {
      this.$router.go(-1)
    }
  }
}
</script>

效果:

ba766fcb7caffce5008326e23ad1a153.png

总结:


使用对应的API来实现导航跳转,就叫做编程式导航。


命名路由

通过 name 属性为路由规则定义名称的方式,叫做命名路由。示例代码如下:

{ 
  // 使用 name 属性为当前的路由规则定义一个“名称”
  name: 'mov', 
  path: '/movie/:id', 
  component: MyMovie ,
  props: true,
},

注意:命名路由的 name 值不能重复,必须保证唯一性!


6.1 使用命名路由实现声明式导航


为 标签动态绑定 to 属性的值,并通过 name 属性指定要跳转到的路由规则。期间还可以用params 属性指定跳转期间要携带的路由参数。示例代码 如下:

<template>
  <h3>MyHome</h3>
  <router-link :to="{ name: 'mov' , params: {id: 3}}">go to Movie</router-link>
</template>
<script>
export default {
  name: 'MyHome'
}
</script>

6.2 使用命名路由实现编程式导航


调用 push 函数期间指定一个配置对象,name 是要跳转到的路由规则、params 是携带的路由参数:

  <template>
  <div>
    <h3>MyHome</h3>
    <router-link :to="{ name: 'mov' , params: {id: 3}}">go to Movie</router-link>
    <button @click="goToMovie(1)"> go to movie </button>
  </div>
</template>
<script>
export default {
  name: 'MyHome',
  methods: {
    goToMovie(id) {
      this.$router.push({
        name: 'mov',
        params: {
          id: id,
        }
      })
    }
  }
}
</script>

总结:


如果在实际项目中,哈希地址比较长的话,建议采用name来进行命名跳转


导航守卫

导航守卫可以控制路由的访问权限。示意图如下:

c8349c799e1005371231942f40a87713.png

7.1 如何声明全局导航守卫


全局导航守卫会拦截每个路由规则,从而对每个路由进行访问权限的控制。可以按照如下的方式定义全局导航守卫:

// 创建路由实例对象
const router = createRouter({ ... })
// 声明全局的导航守卫
  // 调用路由实例对象的 beforeEach 函数,声明 "全局前置守卫"
  // fn 必须是一个函数,每次拦截到路由的请求,都会调用 fn 进行处理
    // 因此 fn 叫做 “守卫方法”
router.beforeEach(fn)

也可以是箭头函数:

router.beforeEach(() => {
  console.log('ok');
})

7.2 守卫方法的 3 个形参


全局导航守卫的守卫方法中接收 3 个形参,格式为:


// 创建路由实例对象
const router = createRouter({ ... })
// 全局前置守卫
router.beforeEach((to, from, next) => {
    // to 目标路由对象
    // from 当前导航正要离开的路由对象
    // next 是一个函数,表示放行
})

注意:

① 在守卫方法中如果不声明 next 形参,则默认允许用户访问每一个路由!

② 在守卫方法中如果声明了 next 形参,则必须调用 next() 函数,否则不允许用户访问任何一个路由!


7.3 next 函数的 3 种调用方式


参考示意图,分析 next 函数的 3 种调用方式最终导致的结果:

20775ff0ad5b8eb0607cf0b0855057e7.png

直接放行:next()


案例:

router.beforeEach((to, from, next) => {
  if(to.path === '/main') {
    // 证明用户要访问后台 主页
    next()
  } else {
    // 访问的不是后台主页
    next()
  }
})

强制其停留在当前页面:next(false)

router.beforeEach((to, from, next) => {
  if(to.path === '/main') {
    // 证明用户要访问后台 主页
    next(false)
  } else {
    // 访问的不是后台主页
    next()
  }
})

强制其跳转到登录页面:next(‘/login’)

 router.beforeEach((to, from, next) => {
  if(to.path === '/main') {
    // 证明用户要访问后台 主页
    next('/login')
  } else {
    // 访问的不是后台主页
    next()
  }
})

7.4 结合 token 控制后台主页的访问权限


目的:通过token来控制后台主页的访问权限


我们先通过localStorage来获取token值,再判断目的地址是否为main以及token值是否存在,


如果用户的token值存在且目的地址为main,则让用户通过,否则让用户进入登陆页面。


这里我通过在Application中设置假token来进入网站:

ed46ad2b6a494b5652d82337cacc2f8c.png

router.beforeEach((to, from, next) => {
  const tokenStr = localStorage.getItem('token') // 1. 获取 token
  if(to.path === '/main' && !token) {  // 2. 想要访问“后台主页”,且token值不存在
    // next(false) // 3.1 不允许跳转
    next('/login') // 3.2 强制跳转到"登陆页面"
  } else {
    next()  // 3.3 直接放行,允许访问“后台主页”
  }
})

理解:从localstorage值获取token值,并且根据访问路径以及token值是否存在来进行下面的逻辑处理


VueCli 自定义创建项目

创建步骤:

1.安装脚手架 (已安装)

npm i @vue/cli -g

2.创建项目

vue create hm-exp-mobile

选项

Vue CLI v5.0.8
? Please pick a preset:
  Default ([Vue 3] babel, eslint)
  Default ([Vue 2] babel, eslint)
> Manually select features     选自定义

手动选择功能

c54c4287b369d93a89c5d1c999fc836c.png

选择vue的版本

  3.x
> 2.x

是否使用history模式

4558a30c653bc2db41e888a380b8c8c9.png

选择css预处理

fe67d3639670871f328cdb3248252b31.png

选择eslint的风格 (eslint 代码规范的检验工具,检验代码是否符合规范)

比如:const age = 18; => 报错!多加了分号!后面有工具,一保存,全部格式化成最规范的样子

b881976ed7be638f13e7fc657c587b84.png

选择校验的时机 (直接回车)

119bb231e4bde3ea1698e11dce53f590.png

选择配置文件的生成方式 (直接回车)

是否保存预设,下次直接使用? => 不保存,输入 N

ea642785acc83f2ca7eed4a3cdcca470.png

等待安装,项目初始化完成

d1b4920b3429302104c5f6dce3bcb59f.png

启动项目

npm run serve

ESlint代码规范及手动修复

代码规范:一套写代码的约定规则。


例如:赋值符号的左右是否需要空格?一句结束是否是要加;?…


没有规矩不成方圆


ESLint:是一个代码检查工具,用来检查你的代码是否符合指定的规则(你和你的团队可以自行约定一套规则)。在创建项目时,我们使用的是 JavaScript Standard Style 代码风格的规则。


1.JavaScript Standard Style 规范说明


建议把:https://standardjs.com/rules-zhcn.html 看一遍,然后在写的时候, 遇到错误就查询解决。


下面是这份规则中的一小部分:


字符串使用单引号 – 需要转义的地方除外

无分号 – 这没什么不好。不骗你!

关键字后加空格 if (condition) { ... }

函数名后加空格 function name (arg) { ... }

坚持使用全等 === 摒弃 == 一但在需要检查 null || undefined 时可以使用 obj == null

2.代码规范错误


如果你的代码不符合standard的要求,eslint会跳出来刀子嘴,豆腐心地提示你。


下面我们在main.js中随意做一些改动:添加一些空行,空格。

import Vue from 'vue'
import App from './App.vue'
import './styles/index.less'
import router from './router'
Vue.config.productionTip = false
new Vue ( {
  render: h => h(App),
  router
}).$mount('#app')

按下保存代码之后:


你将会看在控制台中输出如下错误:

1366b97fdb96388b2bb1e04bbbc8ddc3.png

eslint 是来帮助你的。心态要好,有错,就改。


3.手动修正


根据错误提示来一项一项手动修正。


如果你不认识命令行中的语法报错是什么意思,你可以根据错误代码(func-call-spacing, space-in-parens,…)去 ESLint 规则列表中查找其具体含义。


打开 ESLint 规则表,使用页面搜索(Ctrl + F)这个代码,查找对该规则的一个释义。

53922da314b06e2010d324e339d6edd7.png


通过eslint插件来实现自动修正


eslint会自动高亮错误显示

通过配置,eslint会自动帮助我们修复错误

如何安装

962ca7685555738826c2fe15139701f6.png


如何配置

// 当保存的时候,eslint自动帮我们修复错误
"editor.codeActionsOnSave": {
    "source.fixAll": true
},
// 保存代码,不自动格式化
"editor.formatOnSave": false

注意:eslint的配置文件必须在根目录下,这个插件才能才能生效。打开项目必须以根目录打开,一次打开一个项目

注意:使用了eslint校验之后,把vscode带的那些格式化工具全禁用了 Beatify

settings.json 参考

{
    "window.zoomLevel": 2,
    "workbench.iconTheme": "vscode-icons",
    "editor.tabSize": 2,
    "emmet.triggerExpansionOnTab": true,
    // 当保存的时候,eslint自动帮我们修复错误
    "editor.codeActionsOnSave": {
        "source.fixAll": true
    },
    // 保存代码,不自动格式化
    "editor.formatOnSave": false
}
相关文章
|
17天前
|
JavaScript
【vue】如何跳转路由到指定页面位置
【vue】如何跳转路由到指定页面位置
19 0
|
1月前
|
JavaScript
vue路由导航守卫(全局守卫、路由独享守卫、组件内守卫)
vue路由导航守卫(全局守卫、路由独享守卫、组件内守卫)
41 0
|
2月前
vue3配置路由报错Catch all routes (“*“) must now be defined using a param with a custom regexp.
vue3配置路由报错Catch all routes (“*“) must now be defined using a param with a custom regexp.
54 0
|
18天前
|
资源调度 JavaScript 前端开发
Vue的路由管理:VueRouter的配置和使用
【4月更文挑战第24天】VueRouter是Vue.js的官方路由管理器,用于在单页面应用中管理URL路径与组件的映射。通过安装并引入VueRouter,设置路由规则和创建router实例,可以实现不同路径下显示不同组件。主要组件包括:`&lt;router-link&gt;`用于创建导航链接,`&lt;router-view&gt;`负责渲染当前路由对应的组件。此外,VueRouter还支持编程式导航和各种高级特性,如嵌套路由、路由参数和守卫,以应对复杂路由场景。
|
16天前
|
JavaScript 数据可视化 算法
vue3+threejs可视化项目——搭建vue3+ts+antd路由布局(第一步)
vue3+threejs可视化项目——搭建vue3+ts+antd路由布局(第一步)
36 6
|
3天前
|
JavaScript
vue中watch监听路由传来的参数变化问题
vue中watch监听路由传来的参数变化问题
5 0
|
4天前
|
缓存 JavaScript
在 Vue 组件中使用计算属性和侦听器来响应路由变化
Vue Router 中,计算属性和侦听器常用于根据路由变化更新组件状态。计算属性缓存依赖,当路由参数改变时自动更新,如示例中的 `userId`。侦听器则监听 `$route` 变化,执行相应操作,例如在 `currentUserId` 示例中响应 `userId` 更新。计算属性适合简单变化,而异步操作或复杂场景可选用侦听器。Vue 3 中,`watchEffect` 减少了部分侦听场景的复杂性。总之,它们用于组件内部响应路由变化,而非直接处理路由逻辑。
12 4
|
12天前
|
资源调度 JavaScript 前端开发
【vue】vue中的路由vue-router,vue-cli脚手架详细使用教程
【vue】vue中的路由vue-router,vue-cli脚手架详细使用教程
|
13天前
|
JavaScript Go
Vue路由跳转及路由传参
Vue路由跳转及路由传参
|
17天前
|
JavaScript 前端开发
vue3+ts+element home页面侧边栏+头部组件+路由组件组合页面教程
这是一个Vue.js组件代码示例,展示了带有侧边栏导航和面包屑导航的布局。模板中使用Element Plus组件库,包含可折叠的侧边栏,其中左侧有 Logo 和导航列表,右侧显示更具体的子菜单。`asideDisplay`控制侧边栏宽度。在`script`部分,使用Vue的响应式数据和生命周期钩子初始化路由相关数据,并从localStorage恢复状态。样式部分定义了组件的颜色、尺寸和布局。
19 1