前面我们讲过使用 vue-cli 创建的项目本质上讲是一个 SPA(单页面)项目,而不同页面之间的切换,就需要通过 前端路由 来实现。
# 页面切换:
没有学习 vue 之前,在单个页面中实现页面切换的话,通常采用 display 进行显示和隐藏
在没有学习 vue-Router 之前,我们可以使用动态组件达到同样的效果。
代码实现
组件切换案例 (opens new window)(动态路由版)
那后面我们要使用的Vue Router (opens new window) ,是基于什么原理实现的那?
# 一、路由管理
下面我们可以使用锚链接来模拟一些 vue-router 是实现。
提示
vue-router 默认 hash 模式,如果为了美观可以将其修改为 history 模式。
const router = new VueRouter({
mode: 'history',
routes: [...]
})
但是这样,会导致一些额外的配置 (opens new window)
# 1、锚链接
特点:
地址栏上有浏览历史(location.href
、location.hash
)
原理:
利用 ·
<a>
标签的 href 内容和 id 属性的关联性。
提示
要额外注意 router 盒子的位置 —— 在页面展示之前。
代码 ✍ 实现:
<body>
<!-- 切换控制(key) -->
<div class="router">
<a href="#Home">首页</a>
<a href="#Cart">购物车</a>
<a href="#Search">搜索</a>
</div>
<!-- 页面(value) -->
<div id="Home">home-page<div>
<div id="Cart"><div>
<div id="Search"><div>
</body>
# 2、路由分析
记忆
多个路由 route 可以由一个路由器 router 控制。
上面是利用锚链接与 id 盒子的对应关系,实现了跳转。
这种实现模式,我们同样可以应用在Hash 地址(锚链接)与组件之间的对应关系中。
# 3、实现原理
参照对应关系,我们可以通过动态组件的方式,按照下面的步骤达到同样的效果。
前端路由实现
<template>
<div>
<div class="router">
<a href="#Home">首页</a>
<a href="#Cart">购物车</a>
<a href="#Search">搜索</a>
</div>
<hr/>
<!-- 使用动态组件 -->
<div class="main">
<component :is="componentS"></component>
</div>
<div>
</template>
<script>
import Home from '@/components/Home.vue'
import Cart from '@/components/Cart.vue'
import Search from '@/components/Search.vue'
export default {
data() {
return {
componentS: 'Home'
}
},
components: {
Home,
Cart,
Search
},
created() {
// 监听🚩hash值变化
window.onhashchange = () => {
switch(location.hash) {
case '#/home':
this.comp_Name = 'Home'
break
case '#/cart':
this.comp_Name = 'Cart'
break
case '#/search':
this.comp_Name = 'Search'
break
}
}
}
}
</script>
- 点击页面的路由链接
- URL 地址栏中的 Hash 值变化
- 前端路由监听到 Hash 地址变化
- 将当前 Hash 地址对应的组件渲染到浏览器中
![](https://blog-cloudbed.oss-cn-chengdu.aliyuncs.com/note-taking/20220608082202.png)
# 二、vue-router
通过上面的案例,我们发现手动配置编写路由,十分笨拙,此时就可以使用 vue-router (opens new window) 来简化开发。
原生的锚链接的方式实现跳转,就是它们简单对应关系耦合性太高,不方便管理。而 vue-router 通过将它们间的对应关系抽离出来,单独进行管理,从而完美的解决了问题。
# 1、安装使用 ✨
① 安装
npm i vue-router@3
① 构建 router
- router / index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter) // 插件注册成功(vue中能使用vue-router了)
// 大佬router产生了✍
export default new VueRouter({
//……
routes: [
// 路由规则(对应关系)
{ path: '/home', component: Home },
{ path: '/cart', component: Cart },
{ path: '/search', component: Search }
]
})
② 全局使用
main.js
import router from '@/router/index.js'
new Vue({
router, // router: router的简写
render: (h) => h(App)
}).$mount('#app')
<template>
<div>
<!-- 1、跳转控制区域 -->
<!-- <div class="router">
<a href="#Home">首页</a>
<a href="#Cart">购物车</a>
<a href="#Search">搜索</a>
</div> -->
<router-link to="/home">首页</router-link>
<router-link to="/cart">购物车</router-link>
<router-link to="/search">搜索</router-link>
<hr/>
<!-- 2、展示区域 -->
<!-- <div class="main">
<component :is="componentS"></component>
</div> -->
<div class="main">
<router-view></router-view>
</div>
<div>
</template>
观察
在前面我们使用 vue-router 的时候,我们发现即使我们在路由规则
和 router-link
中都没有加上#/
,但地址栏也会自动帮我们生成。
# 2、懒加载
原先的组件引入方式有一个缺陷就是,不管该组件有没有使用,都得先进行加载。
解决方案:
不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件
代码实现:
// 异步加载
// const Home = () =>
// Promise.resolve({
// import('@/components/Home.vue') // 返回 Promise
// })
// 简化:
const Home = () => import('@/components/Home.vue')
# 三、开发应用
要说 vue-router 的应用,那后台管理必然有一席之地:
![](https://blog-cloudbed.oss-cn-chengdu.aliyuncs.com/note-taking/20230417174613.png)
为了节约时间,我们就直接在原动态组件中的组件切换案例 (opens new window)中进行改造,将其用 vue-router 实现一下。
简单实现
组件切换案例 (opens new window)(vue-router 版)
# 1、重定向
在上面案例中如果我们不使用重定向,那么页面渲染完时,<router-view>
并没有页面显示。
![](https://blog-cloudbed.oss-cn-chengdu.aliyuncs.com/note-taking/20230417194426.png)
原因:
刚进入 HomeView 组件时,默认的路径为
/
,而 vue-router 并没有检测到相关路由配置。
解决:
export default new VueRouter({
routes: [
{
path: '/',
redirect: '/part1' // 重定向✨
},
{
path: '/part1',
component: () => import('../page/PartOne')
}
]
})
# 2、active-class 属性
官方:
还有在上面案例中,我们发现:
<template>
<li>
<router-link active-class="active" to="/part1">part1</router-link>
</li>
<li>
<router-link active-class="active" to="/part2">part2</router-link>
</li>
<li>
<router-link active-class="active" to="/part3">part3</router-link>
</li>
</template>
<style scoped>
.active {
display: inline-block;
background: #efefef;
}
</style>
# 3、注意事项
思考 1:
常规组件 和 路由组件 该怎么区分?
vue-cli_project
├─ src
│ ├─ components(常规组件)
│ │ └─ HelloWorld.vue
│ ├─ pages(路由组件)
│ │ └─ Home.vue
│ ├─ router