这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
1.0 什么是路由?
提到路由,零基础的同学应该最先想到的是路由器,生活中的路由器是为移动设备提供网络的,会为每个设备提供不同的ip地址,生活中的路由就是设备与ip映射的关系,在后台语言如node中的路由就是接口与服务的映射关系,而Vue的路由就是路径与组件的映射关系
2.0 为何使用路由?
要知道,Vue与React等前端框架实现的都是单页应用也就是SPA,一个网站中仅有一个唯一的一个HTML,所有的功能交互都在这唯一的页面中完成
相比传统的多页应用开发,SPA有如下的优势
- 仅在Web页面初始化时加载资源
- 一旦页面加载完成,用户操作
不再进行重加载或者跳转,而是通过路由动态的更改组件展示,不会出现如多页应用的白屏现象 - 减轻服务器压力,前端专注页面渲染,后端专注API实现,利于
前后端分离
所以学习Vue,路由属于必学内容
当然也有一定的缺陷
- 开发成本高(需要单独学习路由知识)
- 首次加载较慢,不利于
seo
3.0 如何在Vue中使用路由?
Vue是一个渐进式框架,所以vue-router并没有默认提供,只需要我们在单独下载一下vue-router包就可以实现Vue相关的路由功能
vue-router是由Vue官方提供的路由管理器,官网地址为Vue Router (vuejs.org)
引自官网的优势为:
- 嵌套路由映射
- 动态路由选择
- 模块化、基于组件的路由配置
- 路由参数、查询、通配符
- 展示由 Vue.js 的过渡系统提供的过渡效果
- 细致的导航控制
- 自动激活 CSS 类的链接
- HTML5 history 模式或 hash 模式
- 可定制的滚动行为
- URL 的正确编码
4.0 使用vue-router模块
使用路由大致有如下步骤
当然可以在构建项目的时候就添加上路由,这种方式更简单,我们优先教学从0自己配置的情况
- 下载
vue-router到当前项目 - main.js中引入
VueRouter函数 - 添加到Vue.use()身上 -> 注册全局
RouterLink与RouterView组件 - 创建路由规则数组 -> 路径与组件名的映射关系
- 用规则生成路由对象
- 把路由对象注入new Vue实例中
- 用
router-view作为挂载点切换不同的路由页面
5.0 router实践
选择vue2.x默认情况
vue create routerdemo
vue.config.js中修改为
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false
})
添加vue-router
yarn add vue-router@3.5.1
本章版本使用的是3.5.1的vue-router
在src目录下创建router与view文件夹,router文件下创建index.js文件,view中创建Dt.vue文件与Wz.vue
index.js文件下
// 引入Vue
import Vue from 'vue'
// 引入VueRouter
import VueRouter from 'vue-router'
// 页面文件
import Dt from '../view/Dt.vue'
Vue.use(VueRouter)
const routes = [
{
// 路径
path: '/Dt',
// 昵称
name: 'Dt',
// 组件
component: Dt
},
{
path: '/Wz',
name: 'Wz',
// 直接引入方式
component: () => import('../view/Wz.vue')
}
]
// 生成路由对象
const router = new VueRouter({
routes // routes是固定key(传入规则数组)
})
// 导出router 在main中注入实例
export default router
main.js中引入并注入实例
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
import router from './router'
new Vue({
// 注入router , this可以直接访问$router与$route
router,
render: h => h(App),
}).$mount('#app')
Dt.vue文件与Wz.vue作为页面组件进行展示,这里就不贴详细代码了,就写个名字区分即可
<template>
<div>文章or动态</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
在App.vue中通过a标签的href属性实现修改页面路径的hash值,实现路由跳转,具体代码如下
<template>
<div>
<div class="header">
<a
:class="{active: current == index,item}"
v-for="(item,index) in list"
:key="item.id"
:href="item.href"
@click="changeActive(index)"
>{{item.name}}</a>
</div>
<div class="msg">
<!-- 设置挂载点 当url的hash值切换,显示规则内对应的组件 -->
<router-view></router-view>
</div>
</div>
</template>
<script>
import ListHeader from '../../vue-life/src/components/listHeader.vue';
export default {
components: { ListHeader },
data () {
return {
current: 0,
list: [{
name: '动态',
href: '#/Dt',
id: 0
}, {
name: '文章',
href: '#/Wz',
id: 1
}, {
name: '专栏',
href: '#/Wz',
id: 2
}, {
name: '沸点',
href: '#/Wz',
id: 3
}, {
name: '收藏集',
href: '#/Wz',
id: 4
}],
ComList: ['DT', 'WZ', 'ZL', 'FD', 'SCJ'],
showComName: 'DT'
};
},
methods: {
changeActive (index) {
this.current = index
this.showComName = this.ComList[index]
}
}
}
</script>
<style>
body {
background-color: #f4f5f5;
}
.msg {
background-color: #fff;
width: 708px;
height: 221px;
margin: 0 auto;
}
.header {
height: 49px;
width: 708px;
background-color: #fff;
margin: 20px auto 0 auto;
display: flex;
border-radius: 0.2rem 0.2rem 0 0;
border-bottom: 1px solid #e4e6eb;
color: #515767;
cursor: pointer;
}
.item:hover {
color: #747985;
}
.item {
font-size: 16px;
height: 49px;
width: 72px;
line-height: 49px;
text-align: center;
color: #252933;
font-weight: 500;
position: relative;
text-decoration: none; /* 去除默认的下划线 */
color: #000; /* 去除默认的颜色和点击后变化的颜色 */
}
.active::after {
content: '';
position: absolute;
width: 16px;
height: 3px;
border-radius: 50px;
left: 50%;
bottom: 0;
transform: translateX(-50%);
z-index: 10;
background-color: #1e80ff;
}
</style>
实现的效果如下
至此,我们已经实现了简单的路由切换,是不是很简单呢?
6.0 声明式导航
vue-router为我们提供了一个全局组件router-linkrouter-link实质上最终会渲染成a标签,to属性等价于提供了href属性并且无需#router-link自带高亮显示to地址相同的都会进行同步高亮
如果高亮展示Vue为我们实现了那么我们就可以节省大部分的判断代码,更为精简代码结构,使用声明式导航后App.js的代码如下
<template>
<div>
<div class="header">
<router-link class="item" v-for="item in list" :key="item.id" :to="item.href">{{item.name}}</router-link>
</div>
<div class="msg">
<!-- 设置挂载点 当url的hash值切换,显示规则内对应的组件 -->
<router-view></router-view>
</div>
</div>
</template>
<script>
import ListHeader from '../../vue-life/src/components/listHeader.vue';
export default {
components: { ListHeader },
data () {
return {
current: 0,
list: [{
name: '动态',
href: '/Dt',
id: 0
}, {
name: '文章',
href: '/Wz',
id: 1
}, {
name: '专栏',
href: '/Wz',
id: 2
}, {
name: '沸点',
href: '/Wz',
id: 3
}, {
name: '收藏集',
href: '/Wz',
id: 4
}],
};
},
methods: {
}
}
</script>
<style>
body {
background-color: #f4f5f5;
}
.msg {
background-color: #fff;
width: 708px;
height: 221px;
margin: 0 auto;
}
.header {
height: 49px;
width: 708px;
background-color: #fff;
margin: 20px auto 0 auto;
display: flex;
border-radius: 0.2rem 0.2rem 0 0;
border-bottom: 1px solid #e4e6eb;
color: #515767;
cursor: pointer;
}
.item:hover {
color: #747985;
}
.item {
font-size: 16px;
height: 49px;
width: 72px;
line-height: 49px;
text-align: center;
color: #252933;
font-weight: 500;
position: relative;
text-decoration: none; /* 去除默认的下划线 */
color: #000; /* 去除默认的颜色和点击后变化的颜色 */
}
/* .active::after {
content: '';
position: absolute;
width: 16px;
height: 3px;
border-radius: 50px;
left: 50%;
bottom: 0;
transform: translateX(-50%);
z-index: 10;
background-color: #1e80ff;
} */
/* 激活后的样式 */
.header .router-link-active::after {
content: '';
position: absolute;
width: 16px;
height: 3px;
border-radius: 50px;
left: 50%;
bottom: 0;
transform: translateX(-50%);
z-index: 10;
background-color: #1e80ff;
}
</style>
效果如图
6.1.0 声明式导航跳转传参
6.1.1 第一种方法
to属性传值语法为/path?属性名=值- 对应页面组件接受传递过来的值
$router.query.参数名
我们尝试将Wz.组件进行修改这样实现每点击一个标签跳转后展示各自的名称
<template>
<div>{{$route.query.name}}</div>
</template>
<script>
export default {
mounted () {
}
}
</script>
<style>
</style>
只需要将App.vue文件中的to方法修改就可以实现展示个标签的名称了
:to="item.href + `?name=${item.name}`"
实现效果如图,需要注意:取得时候用的是$route不是$router
6.1.2 第二种方法
- 路由规则上 定义
/path:参数名称 router-link的to="path/值"- 组件上通过
$route.params.参数名接受
这样用数组循环下来的缺陷是动态的路径将也会被修改,读取不到原本的动态页面了
我们看看实践
App.vue文件下的代码如下
<template>
<div>
<div class="header">
<router-link class="item" v-for="item in list" :key="item.id" :to="item.href">{{item.name}}</router-link>
</div>
<div class="msg">
<!-- 设置挂载点 当url的hash值切换,显示规则内对应的组件 -->
<router-view></router-view>
</div>
</div>
</template>
<script>
import ListHeader from '../../vue-life/src/components/listHeader.vue';
export default {
components: { ListHeader },
data () {
return {
current: 0,
list: [{
name: '动态',
href: '/Dt',
id: 0
}, {
name: '文章',
href: '/Wz',
id: 1
}, {
name: '专栏',
href: '/Wz',
id: 2
}, {
name: '沸点',
href: '/Wz',
id: 3
}, {
name: '收藏集',
href: '/Wz',
id: 4
}],
};
},
methods: {
}
}
</script>
<style>
body {
background-color: #f4f5f5;
}
.msg {
background-color: #fff;
width: 708px;
height: 221px;
margin: 0 auto;
}
.header {
height: 49px;
width: 708px;
background-color: #fff;
margin: 20px auto 0 auto;
display: flex;
border-radius: 0.2rem 0.2rem 0 0;
border-bottom: 1px solid #e4e6eb;
color: #515767;
cursor: pointer;
}
.item:hover {
color: #747985;
}
.item {
font-size: 16px;
height: 49px;
width: 72px;
line-height: 49px;
text-align: center;
color: #252933;
font-weight: 500;
position: relative;
text-decoration: none; /* 去除默认的下划线 */
color: #000; /* 去除默认的颜色和点击后变化的颜色 */
}
/* .active::after {
content: '';
position: absolute;
width: 16px;
height: 3px;
border-radius: 50px;
left: 50%;
bottom: 0;
transform: translateX(-50%);
z-index: 10;
background-color: #1e80ff;
} */
/* 激活后的样式 */
.header .router-link-active::after {
content: '';
position: absolute;
width: 16px;
height: 3px;
border-radius: 50px;
left: 50%;
bottom: 0;
transform: translateX(-50%);
z-index: 10;
background-color: #1e80ff;
}
</style>
Wz.vue文件做简单的修改即可
<div>{{$route.params.name}}</div>
实现效果如下
来看看我的其他章节吧,正在长更中
从0到Vue3企业项目实战【01.Vue的基本概念与学习指南】 - 掘金 (juejin.cn)
从0到Vue3企业项目实战【02.了解并理解Vue指令以及虚拟Dom】 - 掘金 (juejin.cn)
从0到Vue3企业项目实战【03.vue基本api入门】 - 掘金 (juejin.cn)
从0到Vue3企业项目实战【04.从vue组件通讯到eventBus以及vuex(附mock接口与axios简单实践)】 - 掘金 (juejin.cn)
从0到Vue3企业项目实战【05.vue生命周期】 - 掘金 (juejin.cn)
从0到Vue3企业项目实战【06.nextTick使用】 - 掘金 (juejin.cn)
从0到Vue3企业项目实战【07.vue动态组件,组件缓存,组件插槽,子组件直接修改props,自定义指令看这一篇就够了】 - 掘金 (juejin.cn)