Vue2:路由

Vue2:路由

Date: May 28, 2023
Sum: vue-router基本使用、高级用法


单页面应用程序

概念:SPA【Single Page Application】是指所有的功能都在一个html页面上实现

案例

单页应用网站: 网易云音乐 https://music.163.com/

多页应用网站:京东 https://jd.com/

**单页应用 VS 多页面应用:

Untitled

单页应用类网站:系统类网站 / 内部网站 / 文档类网站 / 移动端站点

多页应用类网站:公司官网 / 电商类网站

特点

单页面应用程序将所有的功能局限于一个 web 页面中,仅在该 web 页面初始化时加载相应的资源( HTML、JavaScript 和 CSS)。

一旦页面加载完成了,SPA 不会因为用户的操作而进行页面的重新加载或跳转。而是利用JavaScript 动态地变换 HTML 的内容,从而实现页面与用户的交互。

注意:SPA它是按需更新的,并不是整体更新。因此,它需要更加关注访问路径与组件的对应关系

优点

SPA 单页面应用程序最显著的 3 个优点如下:

① 良好的交互体验

单页应用的内容的改变不需要重新加载整个页面

获取数据也是通过 Ajax 异步获取

没有页面之间的跳转,不会出现“白屏现象”

② 良好的前后端工作分离模式

后端专注于提供 API 接口,更易实现 API 接口的复用

前端专注于页面的渲染,更利于前端工程化的发展

③ 减轻服务器的压力

服务器只提供数据,不负责页面的合成与逻辑的处理,吞吐能力会提高几倍

缺点

任何一种技术都有自己的局限性,对于 SPA 单页面应用程序来说,主要的缺点有如下两个:

① 首屏加载慢

可以通过路由懒加载、代码压缩、CDN 加速、网络传输压缩处理

② 不利于 SEO

SSR 服务器端渲染

如何快速创建 vue 的 SPA 项目

vue 官方提供了两种快速创建工程化的 SPA 项目的方式:

① 基于 vite 创建 SPA 项目 ② 基于 vue-cli 创建 SPA 项目

Untitled


总结:

概念:一个Web网站中只有唯一一个HTML页面,所有的功能与交互都在这唯一的一个页面内完成。

特点:

1.集中所有功能于单页面中,仅在该页面初始化时加载相应的资源。

2.通过JS动态变换页面内容,从而实现页面与用户的交互

优点:

  1. 良好的交互体验

    没有页面跳转,不会有“白屏”现象

  2. 良好的前后端分离模式

    前端专注页面渲染,更利于前端工程化发展;后端专注提供API接口,更易实现API接口复用

  3. 减轻服务端的压力

    服务器只提供数据,不负责页面的合成与逻辑,吞吐能力提高几倍

缺点:

  1. 首屏加载慢

    可以通过代码压缩、CDN加速、路由懒加载、网络传输压缩处理等

  2. 不利于SEO

    SSR服务器端渲染




前端路由的概念与原理

思考:

单页面应用程序,之所以开发效率高,性能好,用户体验好

最大的原因就是:页面按需更新

Untitled

比如当点击【发现音乐】和【关注】时,只是更新下面部分内容,对于头部是不更新的

要按需更新,首先就需要明确:访问路径组件的对应关系!

访问路径 和 组件的对应关系如何确定呢? 路由


路由概念:

概念:路由(英文:router)就是对应关系。路由分为两大类: ① 后端路由 ② 前端路由

回顾:后端路由

后端路由指的是:请求方式、请求地址与 function 处理函数之间的对应关系。

在 node.js 课程中,express路由的基本用法如下:

Untitled



前端路由:

SPA 与前端路由

SPA 指的是一个 web 网站只有唯一的一个 HTML 页面,所有组件的展示与切换都在这唯一的一个页面内完成。此时,不同组件之间的切换需要通过前端路由来实现。

结论:在 SPA 项目中,不同功能之间的切换,要依赖于前端路由来完成!

概念:Vue中的路由指 路径 与 组件 的映射关系,根据路由就能知道不同路径,应匹配渲染相应组件

通俗易懂的概念:Hash 地址与组件之间的对应关系。

我们点击不同的链接,会切换不同的哈希地址。当哈希地址切换,页面上就会展示对应组件。

工作方式

① 用户点击了页面上的路由链接
② 导致了 URL 地址栏中的 Hash 值发生了变化
③ 前端路由监听了到 Hash 地址的变化
④ 前端路由把当前 Hash 地址对应的组件渲染都浏览器中

Untitled

结论:前端路由,指的是 Hash 地址与组件之间的对应关系!

实现简易的前端路由:

步骤1:导入并注册 MyHome、MyMovie、MyAbout 三个组件。示例代码如下:

import MyHome from './MyHome.vue'
import MyAbout from './MyAbout.vue'
import MyMovie from './MyMovie.vue'export default {components: {MyHome, MyMovie, MyAbout,},
}

步骤2:通过 标签的 is 属性,动态切换要显示的组件。示例代码如下:

<template><div><h1>App.vue</h1><component :is="comName">This is a test</component></div>
</template>export default {data() {return {comName: 'MyName', // 要展示的组件的名称}},
}

步骤3:在组件的结构中声明如下 3 个 链接,通过点击不同的 链接,切换浏览器地址栏中的 Hash 值:

<a href="#/home">Home</a>&nbsp;
<a href="#/movie">Movie</a>&nbsp;
<a href="#/about">About</a>

步骤4:在 created 生命周期函数中监听浏览器地址栏中 Hash 地址的变化,动态切换要展示的组件的名称:

window.onhashchange = () => {switch(location.hash) {case '#/home': // 点击了“首页”的链接this.comName = 'my-home'breakcase '#/movie': // 点击了“电影”的链接this.comName = 'my-movie'breakcase '#/about': // 点击了“关于”的链接this.comName = 'my-about'break}}
},
  • Code: App.vue

    <template><div><h1>App.vue</h1><a href="#/home">Home</a>&nbsp;<a href="#/movie">Movie</a>&nbsp;<a href="#/about">About</a>&nbsp;<hr /><component :is="comName">This is a test</component></div>
    </template><script>
    import MyHome from '../01.easy-router/MyHome.vue'
    import MyAbout from '../01.easy-router/MyAbout.vue'
    import MyMovie from '../01.easy-router/MyMovie.vue'export default {name: 'MyApp',data() {return {comName: 'MyName',}},components: {MyHome, MyMovie, MyAbout,},created() {window.onhashchange = () => {switch(location.hash) {case '#/home': // 点击了“首页”的链接this.comName = 'my-home'breakcase '#/movie': // 点击了“电影”的链接this.comName = 'my-movie'breakcase '#/about': // 点击了“关于”的链接this.comName = 'my-about'break}}},}
    </script><style lang="scss" scoped>
    </style>
    



vue-router 的基本使用

基础概念:

概念

vue-router 是 vue.js 官方给出的路由解决方案。它只能结合 vue 项目进行使用,能够轻松的管理 SPA 项目中组件的切换。

作用修改地址栏路径时,切换显示匹配的组件

版本:

vue-router 目前有 3.x 的版本和 4.x 的版本。其中:

vue-router 3.x 只能结合 vue2 进行使用

vue-router 4.x 只能结合 vue3 进行使用

vue-router 3.x 的官方文档地址:https://router.vuejs.org/zh/
vue-router 4.x 的官方文档地址:https://next.router.vuejs.org/

补充官网:https://v3.router.vuejs.org/zh/

说明:Vue 官方的一个路由插件,是一个第三方包



VueRouter 3.x的使用(5+2)

固定5个固定的步骤(不用死背,熟能生巧)

1-下载 VueRouter 模块到当前工程,版本3.6.5

yarn add vue-router@3.6.5
npm install vue-router@3.6.5

2-main.js中引入VueRouter

import VueRouter from 'vue-router'

3-安装注册

Vue.use(VueRouter)

4-创建路由对象

const router = new VueRouter()

5-注入,将路由对象注入到new Vue实例中,建立关联

new Vue({render: h => h(App),router:router
}).$mount('#app')

当我们配置完以上5步之后 就可以看到浏览器地址栏中的路由 变成了 /#/的形式。表示项目的路由已经被Vue-Router管理了

Untitled

案例

main.js

// 路由的使用步骤 5 + 2
// 5个基础步骤
// 1. 下载 v3.6.5
// yarn add vue-router@3.6.5
// 2. 引入
// 3. 安装注册 Vue.use(Vue插件)
// 4. 创建路由对象
// 5. 注入到new Vue中,建立关联import VueRouter from 'vue-router'
Vue.use(VueRouter) // VueRouter插件初始化const router = new VueRouter()new Vue({render: h => h(App),router
}).$mount('#app')

**两个核心步骤:

1-创建需要的组件 (views目录),配置路由规则

Untitled

2-配置导航,配置路由出口(路径匹配的组件显示的位置)

代码中的router-view是用来匹配导航栏的位置的,如果它在代码的上/下面,那么导航栏也在上/下面

如下图所示:

Untitled

App.vue

<div class="footer_wrap"><a href="#/find">发现音乐</a><a href="#/my">我的音乐</a><a href="#/friend">朋友</a>
</div>
<div class="top"><router-view></router-view>
</div>

案例

Untitled

  • Code:

    main.js

    import Vue from 'vue'
    import App from './App.vue'Vue.config.productionTip = falseimport Find from './views/Find'
    import My from './views/My'
    import Friend from './views/Friend'import VueRouter from 'vue-router'
    Vue.use(VueRouter)
    const router = new VueRouter({// routes 路由规则们// route 一条路有规则 { path: 路径, component: 组件}routes: [{ path: '/find', component: Find},{ path: '/my', component: My},{ path: '/friend', component: Friend},]
    })Vue.config.productionTip = falsenew Vue({render: h => h(App),router,
    }).$mount('#app')
    

    App.vue

    <template><div><div class="footer_wrap"><a href="#/find">发现音乐</a><a href="#/my">我的音乐</a><a href="#/friend">朋友</a></div><div class="top"><!-- 路由出口:匹配的组件所展示的位置 --><router-view></router-view></div></div>
    </template><script>
    export default {};
    </script><style>
    body {margin: 0;padding: 0;
    }
    .footer_wrap {position: relative;left: 0;top: 0;display: flex;width: 100%;text-align: center;background-color: #333;color: #ccc;
    }
    .footer_wrap a {flex: 1;text-decoration: none;padding: 20px 0;line-height: 20px;background-color: #333;color: #ccc;border: 1px solid black;
    }
    .footer_wrap a:hover {background-color: #555;
    }
    </style>
    


vue-router 4.x的基本使用步骤:

vue-router 4.x 的基本使用步骤

① 在项目中安装 vue-router

② 定义路由组件

③ 声明路由链接和占位符

④ 创建路由模块

⑤ 导入并挂载路由模块

3.1 在项目中安装 vue-router

在 vue3 的项目中,只能安装并使用 vue-router 4.x。安装的命令如下:

npm install vue-router@next -S

注意:包名会被注册在package.json的dependencies里面,在生产环境下这个包的依赖依然存在。

3.2 定义路由组件

在项目中定义 MyHome.vue、MyMovie.vue、MyAbout.vue 三个组件,将来要使用 vue-router 来控制它们的展示与切换:

MyAbout, 其余同理:

<template><h3>MyAbout</h3>
</template><script>
export default {name: 'MyAbout'
}
</script><style></style>

3.3 声明路由链接和占位符

可以使用 标签来声明路由链接,并使用 标签来声明路由占位符。

示例代码如下:

<template><div><h1>MyApp</h1><!-- 声明路由链接 --><router-link to="/home">首页</router-link>&nbsp;<router-link to="/movie">电影</router-link>&nbsp;<router-link to="/about">关于</router-link><hr /><!-- 路由的占位符 --><router-view></router-view></div>
</template>

注意:在声明哈希属性时,需要用to属性来声明,而且哈希地址不再需要以#开头,vue中的router会自动为我们添加#。

3.4 创建路由模块

在项目中创建 router.js 路由模块,在其中按照如下 4 个步骤创建并得到路由的实例对象:

① 从 vue-router 中按需导入两个方法
② 导入需要使用路由控制的组件
③ 创建路由实例对象
④ 向外共享路由实例对象
⑤ 在 main.js 中导入并挂载路由模块

从 vue-router 中按需导入两个方法

// 1. 从 vue-router 中按需导入两个方法
// createRouter 方法用于创建路由的实例对象
// createWebHashHistory 用于指定路由的工作模式(hash模式)
import { createRouter, createWebHashHistory } from 'vue-router'

导入需要使用路由控制的组件

//2. 导入组件,这些组件将要以路由的方式,来控制它们的切换
import MyHome from './MyHome.vue'
import MyMoive from './MyMoive.vue'
import MyAbout from './MyAbout.vue'

创建路由实例对象

// 3. 创建路由实例对象
const router = createRouter({// 3.1 通过 history 属性指定路由的工作模式history: createWebHashHistory(),// 3.2 通过 routes 数组,指定路由规则routes: [// path 是 hash 地址, component 是要展示的组件{ path: '/home', component: Home },{ path: '/movie', component: Movie },{ path: '/about', component: About },]
})

向外共享路由实例对象

// 4. 向外共享路由实例对象,
//   供其他模块导入并使用
export default router

在 main.js 中导入并挂载路由模块

import { createApp } from 'vue'
import App from './components/App.vue'
import './index.css'// 1. 导入路由模块
import router from './components/02.start/router'
const app = createApp(App)// 2. 挂载路由模块
// app.use() 方法用来挂载“第三方的插件模块”
app.use(router)app.mount('#app')

效果:

Untitled



整体流程:

当我们点击电影时,地址栏会切换成 #/movie,当哈希地址发生变化,就会被路由模块所监听到,然后进行哈希地址的匹配:

// router.js
routes: [// path 是 hash 地址, component 是要展示的组件{ path: '/home', component: MyHome },{ path: '/movie', component: MyMovie },{ path: '/about', component: MyAbout },]

当匹配到,我们就会把相应的组件比如MyMovie放到App.vue中的路由占位符中

// App.vue
<template><div><h1>MyApp</h1><!-- 声明路由链接 --><router-link to="/home">首页</router-link><router-link to="/movie">电影</router-link><router-link to="/about">关于</router-link><hr /><!-- 路由的占位符 --><router-view></router-view></div>
</template>


组件的存放目录问题

注意: .vue文件 本质无区别

组件分类:

.vue文件分为2类,都是 .vue文件(本质无区别)

  • 页面组件 (配置路由规则时使用的组件)
  • 复用组件(多个组件中都使用到的组件)

Untitled

存放目录:

分类开来的目的就是为了 更易维护

  1. src/views

    文件夹页面组件 - 页面展示 - 配合路由用

  2. src/components

    文件夹复用组件 - 展示数据 - 常用于复用



路由的封装抽离

问题:所有的路由配置都在main.js中合适吗?

目标:将路由模块抽离出来。 好处:拆分模块,利于维护

Untitled

路径简写:

脚手架环境下 @指代src目录,可以用于快速引入组件

具体书写:

index.js

import Find from '@/views/Find'
import My from '@/views/My'
import Friend from '@/views/Friend'// 1. 导入Vue
import Vue from 'vue'
import VueRouter from 'vue-router'Vue.use(VueRouter)
const router = new VueRouter({// routes 路由规则们// route 一条路有规则 { path: 路径, component: 组件}routes: [{ path: '/find', component: Find},{ path: '/my', component: My},{ path: '/friend', component: Friend},]
})// 2. 导出
export default router

main.js

import Vue from 'vue'
import App from './App.vue'
// 3. 导入 router
import router from './router/index'Vue.config.productionTip = falsenew Vue({render: h => h(App),router,
}).$mount('#app')

App.vue

<template><div><div class="footer_wrap"><a href="#/find">发现音乐</a><a href="#/my">我的音乐</a><a href="#/friend">朋友</a></div><div class="top"><!-- 路由出口:匹配的组件所展示的位置 --><router-view></router-view></div></div>
</template><script>
export default {};
</script><style>
body {margin: 0;padding: 0;
}
.footer_wrap {position: relative;left: 0;top: 0;display: flex;width: 100%;text-align: center;background-color: #333;color: #ccc;
}
.footer_wrap a {flex: 1;text-decoration: none;padding: 20px 0;line-height: 20px;background-color: #333;color: #ccc;border: 1px solid black;
}
.footer_wrap a:hover {background-color: #555;
}
</style>



声明式导航

导航链接

需求:实现导航高亮效果

Untitled

如果使用a标签进行跳转的话,需要给当前跳转的导航加样式,同时要移除上一个a标签的样式,太麻烦!!!

**解决方案:

vue-router 提供了一个全局组件 router-link (取代 a 标签)

  • 跳转,配置 to 属性指定路径(必须) 。本质还是 a 标签 ,to 无需 #
  • 能高亮,默认就会提供高亮类名,可以直接设置高亮样式

Untitled

语法: 发现音乐

<div><div class="footer_wrap"><router-link to="/find">发现音乐</router-link><router-link to="/my">我的音乐</router-link><router-link to="/friend">朋友</router-link></div><div class="top"><!-- 路由出口 → 匹配的组件所展示的位置 --><router-view></router-view></div>
</div>

通过router-link自带的两个样式进行高亮:

使用router-link跳转后,我们发现。当前点击的链接默认加了两个class的值 router-link-exact-activerouter-link-active

我们可以给任意一个class属性添加高亮样式即可实现功能

代码

  • Code:

    App.vue

    <template><div><div class="footer_wrap"><router-link to="/find">发现音乐</router-link><router-link to="friend">我的音乐</router-link><router-link to="my">我的朋友</router-link></div><div class="top"><!-- 路由出口 → 匹配的组件所展示的位置 --><router-view></router-view></div></div>
    </template><script>
    export default {};
    </script><style>
    body {margin: 0;padding: 0;
    }
    .footer_wrap {position: relative;left: 0;top: 0;display: flex;width: 100%;text-align: center;background-color: #333;color: #ccc;
    }
    .footer_wrap a {flex: 1;text-decoration: none;padding: 20px 0;line-height: 20px;background-color: #333;color: #ccc;border: 1px solid black;
    }
    .footer_wrap a.router-link-active {background-color: purple;
    }
    .footer_wrap a:hover {background-color: #555;
    }
    </style>
    


两个类名

当我们使用跳转时,自动给当前导航加了两个类名

Untitled

router-link-active

模糊匹配(用的多)

to=“/my” 可以匹配 /my /my/a /my/b …

只要是以/my开头的路径 都可以和 to="/my"匹配到

router-link-exact-active

精确匹配

to=“/my” 仅可以匹配 /my

在地址栏中输入二级路由查看类名的添加

Untitled

理解:即使地址栏后面加上了 /one ,也就是所谓的二级地址,我们通过模糊匹配router-link-active

也能够让他变色。


自定义类名

问题:router-link的两个高亮类名 太长了,我们希望能定制怎么办

解决方案

我们可以在创建路由对象时,额外配置两个配置项即可。 linkActiveClasslinkExactActiveClass

const router = new VueRouter({routes: [...],linkActiveClass: "类名1",linkExactActiveClass: "类名2"
})

Untitled

详细操作过程

Style:

.footer_wrap a.router-link-active {background-color: purple;
}

经过main.js配置过后

const router = new VueRouter({// routes 路由规则们// route  一条路由规则 { path: 路径, component: 组件 }routes: [{ path: '/find', component: Find },{ path: '/my', component: My },{ path: '/friend', component: Friend },],// link 自定义高亮linkActiveClass: 'active',linkExactActiveClass: 'exact-active'
})

style可以简化成如下:

.footer_wrap a.active {background-color: purple;
}


跳转传参:

目标:在跳转路由时,进行传参

Untitled

比如:当在搜索页点击了热门搜索链接,跳转到详情页,要把点击的内容带到详情页,该怎么办呢?

**跳转传参:

我们可以通过两种方式,在跳转的时候把所需要的参数传到其他页面中

  • 查询参数传参
  • 动态路由传参

**查询参数传参:

  • 如何传参?
  • 如何接受参数固定用法:
    • $router.query.参数名

案例

Untitled

  • Code:

    Home.vue

    <template><div class="home"><div class="logo-box"></div><div class="search-box"><input v-model="inpValue" type="text"><button @click="goSearch">搜索一下</button></div><div class="hot-link">热门搜索:<router-link to="/search/黑马程序员?key=test">黑马程序员</router-link><router-link to="/search/前端培训">前端培训</router-link><router-link to="/search/如何成为前端大牛">如何成为前端大牛</router-link></div></div>
    </template><script>
    export default {name: 'FindMusic',data() {return {inpValue: '',}},methods: {goSearch() {this.$router.push(`/search${this.inpValue}`)}}
    }
    </script><style>
    .logo-box {height: 150px;background: url('@/assets/logo.jpeg') no-repeat center;
    }
    .search-box {display: flex;justify-content: center;
    }
    .search-box input {width: 400px;height: 30px;line-height: 30px;border: 2px solid #c4c7ce;border-radius: 4px 0 0 4px;outline: none;
    }
    .search-box input:focus {border: 2px solid #ad2a26;
    }
    .search-box button {width: 100px;height: 36px;border: none;background-color: #ad2a26;color: #fff;position: relative;left: -2px;border-radius: 0 4px 4px 0;
    }
    .hot-link {width: 508px;height: 60px;line-height: 60px;margin: 0 auto;
    }
    .hot-link a {margin: 0 5px;
    }
    </style>
    

    Search.vue

    <template><div class="search"><p>搜索关键字: {{ $route.query.key }}</p><p>搜索结果: </p><ul><li>.............</li><li>.............</li><li>.............</li><li>.............</li></ul></div>
    </template><script>
    export default {name: 'MyFriend',created () {// 在created中,获取路由参数// this.$route.query.参数名 获取console.log(this.$route.query.key);}
    }
    </script><style>
    .search {width: 400px;height: 240px;padding: 0 20px;margin: 0 auto;border: 2px solid #c4c7ce;border-radius: 5px;
    }
    </style>
    

注意:如果在像created这种的js代码中,不要忘记加上this.


动态路由传参方式

配置动态路由步骤:

1-配置动态路由

动态路由后面的参数可以随便起名,但要有语义

index.js

const router = new VueRouter({routes: [...,{ path: '/search/:words', component: Search }]
})

2-配置导航链接

Home.vue

to="/path/参数值"

3-对应页面组件接受参数

Search.vue

{{ $route.params.参数名 }}

params后面的参数名要和动态路由配置的参数保持一致

案例

Untitled

  • Code:

    index.js

    import Home from '@/views/Home'
    import Search from '@/views/Search'
    import Vue from 'vue'
    import VueRouter from 'vue-router'
    Vue.use(VueRouter) // VueRouter插件初始化// 创建了一个路由对象
    const router = new VueRouter({routes: [{ path: '/home', component: Home },// *** 1, 配置动态路由{ path: '/search/:words', component: Search }]
    })export default router
    

    Home.vue

    // *** 2, 配置导航链接
    <router-link to="/search/letstry">Vue-test</router-link>
    

    Search.vue

    <template><div class="search"><!-- *** 3, 对应页面组件接收参数 --><p>搜索关键字: {{ $route.params.words }}</p><p>搜索结果: </p><ul><li>.............</li><li>.............</li><li>.............</li><li>.............</li></ul></div>
    </template><script>
    export default {name: 'MyFriend',created () {// 在created中,获取路由参数// this.$route.query.参数名 获取console.log(this.$route.query.key);}
    }
    </script><style>
    .search {width: 400px;height: 240px;padding: 0 20px;margin: 0 auto;border: 2px solid #c4c7ce;border-radius: 5px;
    }
    </style>
    

查询参数传参 VS 动态路由传参

  1. 查询参数传参 (比较适合传多个参数)
    1. 跳转:to=“/path?参数名=值&参数名2=值”
    2. 获取:$route.query.参数名
  2. 动态路由传参 (优雅简洁,传单个参数比较方便)
    1. 配置动态路由:path: “/path/:参数名”
    2. 跳转:to=“/path/参数值”
    3. 获取:$route.params.参数名

注意:动态路由也可以传多个参数,但一般只传一个


动态路由参数的可选符(了解)

问题:配了路由 path:“/search/:words” 为什么按下面步骤操作,会未匹配到组件,显示空白?

Untitled

原因:/search/:words 表示,必须要传参数。如果不传参数,也希望匹配,可以加个可选符"?"

const router = new VueRouter({routes: [...{ path: '/search/:words?', component: Search }]
})


Vue路由

重定向

**问题:**网页打开时, url 默认是 / 路径,未匹配到组件时,会出现空

Untitled

解决方案:重定向 → 匹配 / 后, 强制跳转 /home 路径

语法:

{ path: 匹配路径, redirect: 重定向到的路径 },
比如:
{ path:'/' ,redirect:'/home' }

代码:

const router = new VueRouter({routes: [{ path: '/', redirect: '/home'},...]
})


404

**作用:**当路径找不到匹配时,给个提示页面

位置:404的路由,虽然配置在任何一个位置都可以,但一般都配置在其他路由规则的最后面

**语法:**path: “*” (任意路径) – 前面不匹配就命中最后这个

import NotFind from '@/views/NotFind'const router = new VueRouter({routes: [...{ path: '*', component: NotFind } //最后一个]
})


模式设置

问题:

路由的路径看起来不自然, 有#,能否切成真正路径形式?

  • hash路由(默认) 例如: http://localhost:8080/#/home
  • history路由(常用) 例如: http://localhost:8080/home (以后上线需要服务器端支持,开发环境webpack给规避掉了history模式的问题)

理解

1-hash模式:底层是由a标签,锚链接实现的

2-history模式:由新增的HTML5中的historyAPI实现

语法:

const router = new VueRouter({mode:'histroy', //默认是hashroutes:[]
})

注意:一旦采用了 histroy 模式,地址栏就没有 # ,需要后台配置访问规则



两种路由跳转方式

两种路径直接跳转

**问题:**点击按钮跳转如何实现?

Untitled

**方案:**编程式导航:用JS代码来进行跳转

语法:

两种语法:

  • path 路径跳转 (简易方便)
  • name 命名路由跳转 (适合 path 路径长的场景)

path路径跳转语法:

特点:简易方便

Home.vue

//简单写法
this.$router.push('路由路径')
//eg
this.$router.push(`/search${this.inpValue}`)//完整写法
this.$router.push({path: '路由路径'
})

代码

  • Code:

    Home.vue中的script

    export default {name: 'FindMusic',methods: {goSearch() {// Plan1: 简易写法// this.$router.push('/search')// Plan2: 完整写法this.$router.push({path: '/search'})}}
    }
    

**name命名路由跳转:

特点:适合 path 路径长的场景

语法:

  • 路由规则,必须配置name配置项

index.js

{ name: '路由名', path: '/path/xxx', component: XXX },
  • 通过name来进行跳转

Home.vue

this.$router.push({name: '路由名'
})

理解:给routes下的route起别名,方便自己之后push路径

代码演示通过name命名路由跳转:

  • Code:

    index.js

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

    Home.vue

    export default {name: 'FindMusic',methods: {goSearch() {this.$router.push({name: 'search',})}}
    }
    


问题:点击搜索按钮,跳转需要把文本框中输入的内容传到下一个页面如何实现?

Untitled

**两种传参方式:

1.查询参数

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路径长的场景




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

效果与功能分析:

面经效果演示

Untitled

功能分析

1-配路由

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

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

2-实现功能

首页请求渲染

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

组件缓存,优化性能

Untitled



一级路由配置:

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()

Untitled

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走的是动态参数

关键

优化空白界面:

Untitled

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

原理:在请求和响应中间,不让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.creatorAvataralt=""/><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.idconst { 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>
    


缓存组件

问题:

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

Untitled

原因:

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


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

keep-alive

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

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

优点:

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

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

keep-alive的三个属性

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

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

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

案例

对Layout页面进行缓存

Untitled

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

Untitled


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

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

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

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

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

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

理解:

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

Untitled

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

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

Untitled

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

Untitled

总结

  1. keep-alive是什么
    vue 的内置组件,包裹动态组件时,可以缓存
  2. keep-alive的优点
    组件切换过程中 把切换出去的组件保留在内存中(提升性能)
  3. keep-alive的三个属性(了解)
    1-include:组件名数组,只有匹配的组件会被缓存
    2-exclude :组件名数组,任何匹配的组件都不会被缓存
    3-max:最多可以缓存多少组件实例
  4. keep-alive的使用会触发两个生命周期函数(了解)
    activated 当组件被激活(使用)的时候触发 → 进入页面触发
    deactivated 当组件不被使用的时候触发 → 离开页面触发


面经总结:

Untitled




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;
}

效果:

Untitled


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 },]
})


嵌套路由

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

Untitled

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

② 在父路由规则中,通过 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中的内容:

Untitled

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>

效果:

Untitled

总结:

使用对应的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来进行命名跳转



导航守卫

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

Untitled

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 种调用方式最终导致的结果:

Untitled

直接放行: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来进入网站:

Untitled

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

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




VueCli 自定义创建项目

创建步骤:

Untitled

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     选自定义
  • 手动选择功能

Untitled

  • 选择vue的版本
  3.x
> 2.x
  • 是否使用history模式

Untitled

  • 选择css预处理

Untitled

  • 选择eslint的风格 (eslint 代码规范的检验工具,检验代码是否符合规范)
  • 比如:const age = 18; => 报错!多加了分号!后面有工具,一保存,全部格式化成最规范的样子

Untitled

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

Untitled

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

Untitled

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

Untitled

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

Untitled

  • 启动项目
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 = falsenew Vue ( {render: h => h(App),router
}).$mount('#app')

按下保存代码之后:

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

Untitled

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

3.手动修正

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

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

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

Untitled



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

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

  • 如何安装

Untitled

  • 如何配置
// 当保存的时候,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
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/30828.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Idea使用Docker插件实现maven打包自动构建镜像

Docker 开启TCP 服务 vi /lib/systemd/system/docker.service改写以下内容 ExecStart/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock重启服务 #重新加载配置文件 systemctl daemon-reload #重启服务 systemctl restart docker.service此时docker已…

大数据课程I1——Kafka的概述

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 了解Kafka的概念&#xff1b; ⚪ 掌握Kafka的配置与启动&#xff1b; 一、简介 1. 基本概念 Apache kafka 是一个分布式数据流平台。可以从如下几个层面来理解&#x…

elasticsearch-head可视化安装

一、前言 elasticsearch-head 是用于监控 Elasticsearch 状态的客户端插件&#xff0c;包括数据可视化、执行增删改查操作等。 elasticsearch是通过API方式进行管理的&#xff0c;因此也可以使用postman等工具操作elasticsearch。 二、安装 lasticsearch-head插件是使用Jav…

C++核心编程——函数高级、类和对象

3 函数提高 3.1 函数默认参数 在C中&#xff0c;函数的形参列表中的形参是可以有默认值的。 语法&#xff1a;返回值类型 函数名 &#xff08;参数默认值&#xff09;{} 注意事项&#xff1a; 1、如果函数的参数列表中某个参数已经有了默认参数&#xff0c;那么从这个参…

cve-2021-2394 weblogic反序列化漏洞分析

前几天weblogic 7月例行更新中&#xff0c;修复了一个Rce漏洞。该漏洞性质属于绕过之前的反序列化漏洞补丁。要了解这个漏洞的原因&#xff0c;我们首先要学习其他几个漏洞的原理。 一 weblogic 反序列化绕过指南 本章节只是大概讲解一下如何绕过weblogic反序列化漏洞的补丁。…

解决selenium的“can‘t access dead object”错误

目录 问题描述 原因 解决方法 示例代码 资料获取方法 问题描述 在python执行过程中&#xff0c;提示selenium.common.exceptions.WebDriverException: Message: TypeError: cant access dead object 原因 原因是代码中用到了frame,获取元素前需要切换到frame才能定位到…

苍穹外卖day11笔记

今日首先介绍前端技术Apache ECharts&#xff0c;说明后端需要准备的数据&#xff0c;然后讲解具体统计功能的实现&#xff0c;包括营业额统计、用户统计、订单统计、销量排名。 一、ECharts 是什么 ECharts是一款基于 Javascript 的数据可视化图表库。我们用它来展示图表数…

一次面试下来Android Framework 层的源码就问了4轮

说起字节跳动的这次面试经历&#xff0c;真的是现在都让我感觉背脊发凉&#xff0c;简直被面试官折磨的太难受了。虽然已经工作了七年&#xff0c;但是也只是纯粹的在写业务&#xff0c;对底层并没有一个很深的认识&#xff0c;这次面试经历直接的让我感受到我和那些一线大厂开…

Client not connected, current status:STARTING

今天项目集成Seata时遇到一个奇怪的异常&#xff0c;在此记录一下。 Linux环境安装Seata&#xff0c;使用Nacos作为配置中心、注册中心&#xff1b; Linux已开放端口&#xff1a;8848、7091、8091 在我Windows环境下可以看到Nacos运行正常&#xff0c;Seata运行也正常&#…

【腾讯云 Cloud Studio 实战训练营】用于编写、运行和调试代码的云 IDE泰裤辣

文章目录 一、引言✉️二、什么是腾讯云 Cloud Studio&#x1f50d;三、Cloud Studio优点和功能&#x1f308;四、Cloud Studio初体验&#xff08;注册篇&#xff09;&#x1f386;五、Cloud Studio实战演练&#xff08;实战篇&#xff09;&#x1f52c;1. 初始化工作空间2. 安…

学习笔记-JAVAJVM-JVM的基本结构及概念

申明&#xff1a;文章内容是本人学习极客时间课程所写&#xff0c;文字和图片基本来源于课程资料&#xff0c;在某些地方会插入一点自己的理解&#xff0c;未用于商业用途&#xff0c;侵删。 原资料地址&#xff1a;课程资料 什么是JVM 原文连接&#xff1a; 原文连接 JVM是J…

谷歌推出AI模型机器人RT2 将文本和图像输出为机器人动作

去年年底&#xff0c;ChatGPT火遍全球&#xff0c;全世界都见识了大语言模型的强大力量。人们对大模型不再陌生&#xff0c;开始使用基于大模型的应用绘画、作图、搜索资料、设计剧情等&#xff0c;而妙用不止于此。谷歌推出了Robotics Transformer 2(RT2)&#xff0c;这是一个…

分布式 - 消息队列Kafka:Kafka生产者架构和配置参数

文章目录 1. kafka 生产者发送消息整体架构2. Kafka 生产者重要参数配置01. acks02. 消息传递时间03. linger.ms04. buffer.memory05. batch.size06. max.in.flight.requests.per.connection07. compression.type08. max.request.size09. receive.buffer.bytes和 send.buffer.b…

【PyQt5+matplotlib】获取鼠标在canvas上的点击坐标

示例代码&#xff1a; import sys import matplotlib.pyplot as plt from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvasclass MyMainWindow(QMainWindow):de…

UE4 像素流 学习笔记

使用场景&#xff1a; 1、登录服务器&#xff0c;服务器上安装node.js Download | Node.js (nodejs.org) 点击该网址 点击Windows Installer 2、登录服务器&#xff0c;拷贝本地UE Pixel Streaming包到服务器 启用插件后重启该项目 然后打包 打包成功过后创建快捷方式 将该I…

SDU Crypto School - 计算不可区分性1

Encryption: Computational security 1-4 主讲人&#xff1a;李增鹏&#xff08;山东大学&#xff09; 参考教材&#xff1a;Jonathan Katz, Yehuda Lindell, Introduction to Modern Cryptography - Principles and Protocols. 什么是加密 首先&#xff0c;加密方案的目的在于…

网络:CISCO、Huawei、H3C命令对照

思科、华为、锐捷命令对照表 编号思科华为锐捷命令解释1 2writesavesave保存3456 如果你所处的视图为非系统视图&#xff0c;需要查看配置的时候&#xff0c;需要在该配置命令前加do。 在特定的视图之下&#xff0c;有对应的特定命令。例如&#xff0c;在接口视图下的ip addre…

Ubuntu18.04使用carla0.9.5联合仿真搭环境报错

Ubuntu18.04使用工程与carla0.9.5联合仿真报错 1 File "/home/cg/Auto_driving/src/ros-bridge/carla_ros_bridge/src/carla_ros_bridge/client.py", line 18, in <module>from carla_ros_bridge.bridge_with_rosbag import CarlaRosBridgeWithBagFile "…

[保研/考研机试] KY180 堆栈的使用 吉林大学复试上机题 C++实现

题目链接&#xff1a; 堆栈的使用_牛客题霸_牛客网 描述 堆栈是一种基本的数据结构。堆栈具有两种基本操作方式&#xff0c;push 和 pop。其中 push一个值会将其压入栈顶&#xff0c;而 pop 则会将栈顶的值弹出。现在我们就来验证一下堆栈的使用。 输入描述&#xff1a; 对于…