单页面应用的特点,什么是路由,VueRouter的下载,安装和使用,路由的封装抽离,声明式导航与编程式导航的介绍和使用

一.什么是单页面应用?

  • 单页只有一个HTML页面,按需更新性能高,开发效率快,用户体验好,但学习成本高,首屏加载慢,SEO较差
  • 多页即多个HTML页面,整页更新的特点让其性能较低,开发效率一般,用户体验一般,学习成本中等,但首屏加载快,SEO较好

*SEO:搜索引擎优化,可以理解为搜索结果的友好度

使用场景:

  • 单页:系统类网站,内部网站,文档类网站,移动端网站,比如:网易云音乐
  • 多页:公司官网,电商类网站,比如;:淘宝,京东

二.什么是路由?

由于单页面应用的按需更新的特点,我们必须明确访问路径组件的对应关系
这就需要用到路由,它实际上是一种映射关系

生活中的路由和Vue中的路由

路由器:IP和设备之间的映射关系
Vue中的路由:路径和组件之间的映射关系
示例:

http://localhost:8080#home路径 映射到 Home.vue组件
http://localhost:8080#comment路径 映射到 Comment.vue组件
http://localhost:8080#search路径 映射到 Search.vue组件

三.VueRouter(重点)

0.引出

在单页面应用中,点击导航栏的不同标签,需要实现:
1,地址栏中的地址要发生变化.2.导航栏下方的组件也要对应变化

----Vue官方提供了一个插件可实现以上功能,即VueRouter

1.介绍
  • 作用:修改地址栏地址时,切换显示匹配的组件
  • 本质:Vue官方的一个路由插件,是一个第三方包
2.下载与使用(5+2)
2.1 五个基本步骤
  • 下载:下载VueRouter模块到当前工程项目中(Vue.2对应的版本是3.6.5)*
安装命令:yarn add vue-router@3.6.5:此命令安装报错,最后用了这个命令:
npm install vue-router@3.6.5 -g

*对于安装版本的匹配,有个口诀叫"233 344",:
Vue2+VueRouter3.x+Vuex3.x
"344"同理
  • 引入
//main.js==>若不考虑路由的封装和抽离,所有路由相关代码可先堆在main.js中
import VueRouter from 'vue-router'
  • 安装注册
//由于VueRouter是Vue的插件,所以必须先安装注册后才能使用
Vue.use(VueRouter)//内部会对组件进行全局的注册,即插件的初始化
  • 创建路由对象
const router=new VueRouter();//此时的路由对象和Vue实例还没有建立关联
  • 注入:将路由对象注入到new Vue实例中,建立关联
new Vue({
	render:h=>h(App),
	//router:router可简写如下:
	router
}).$mounted("#app");
//注入完成,代表着这个Vue实例已经被路由对象接管了
//效果:地址栏最后会多出一个"#"

完整代码:main.js

//1.下载:在根目录文件下下载:npm install vue-router@3.6.5 -g

//main.js
//2.引入
import VueRouter from "vue-router"
//3.安装注册
Vue.use(VueRouter);//VueRouter插件初始化
//4.创建路由对象
const router=new VueRouter();//后续可以在里面添加路由规则
//5.注入
new Vue({
    render:h=>h(app),
    router,//router:router,简写成router,(router:rOther)
}).$mount("#app")//当前vue实例已被路由对象所管理
//成功标志:地址栏多了"#"
2.2 两个核心步骤
  • 项目代码
//App.vue
<div class="footer_warp">
     <a>发现音乐</a>
     <a>我的音乐</a>
     <a>好友</a>
</div>
//新建Views文件夹下的FindMusic.vue,MyMusic.vue和MyFriends.vue三个组件,
//内容随意,引入过程略
  • step1:配置规则
//main.js或router/index.js
import FindMusic from "..."
...
const router =new VueRouter({
	routes:[//配置规则
    {path:'/FindMusic',component:FindMusic},
    {path:'/MyMusic',component:MyMusic},
    {path:'/MyFriends',component:MyFriends},
    //此处可直观看到路由的定义:path和component之间的映射
});

*注意:path中的路径没有"."在前面,不要写成相对路径

  • step2:配置导航
     <a href="#/FindMusic"">发现音乐</a>
     <a href="#/MyMusic">我的音乐</a>
     <a href="#/MyFriends">好友</a>
     <div>
     	<!-- 这个标签的位置决定了组件内容展示的位置-->
 	   <router-view></router-view>
	</div>

最终效果:点击不同的a标签,地址栏显示不同的"#"(路径)

四.路由的封装抽离

1.把路由配置从main.js中抽离出来,放在router/index.js中

把所有的路由配置都放在main.js显然是不合适的,因此要将路由模块抽离出来,更利于维护

  • 步骤

把刚刚在main.js 中写的路由相关的代码挪到新建的router/index.js中然后在main,js中导入

import router from "./router/index.js"
  • 注意事项
  1. 把代码放入index.js 后,相对路径会发生变化,此时要么调整成正确的相对路径,要么使用"@"(代表src文件夹),写成绝对路径
  2. 需要在index.js中重新引入Vue,因为使用到了Vue.use(VueRouter),其实main.js也有,只是引用语句import Vue from "vue"在main,js中是自动生成的
  3. 最后需将路由对象导出:export default router;
2.同是存在组件的文件夹,views和components有何区别?
views目录

此文件夹中存放的是路由级的页面组件,对应的是路由配置的入口组件,包含完整的页面结构和业务逻辑,
比如Home.vue,Search.vue

components目录

此文件夹中存放的是可复用的UI组件,这些组件通常是被多个视图或组件调用的复用组件,一般来说只有单一的功能,
比如:Card.vue,Banner.vue

五.声明式导航

在Vue2中:声明式导航就是<router-link to=""></router-link>,
<router-link to=""></router-link>就是声明式导航-----与声明式导航相对的是编程式导航

1.导航链接

使用vue-router的全局组件<router-link to=""></router-link>代替a标签,可以实现导航高亮效果

特点一:能跳转
<router-link to="/FindMusic">发现音乐</router-link>
<!-- to不可省略且不用在路径中加"#",  对比a标签:-->
<a href="#/FindMusic"">发现音乐</a>
特点二:能高亮

声明式导航能实现自动高亮,默认提供高亮类名,可以通过高亮类名设置高亮样式
(在控制台能看到选中的a标签自动获得两个类名)
route-link本质上还是a标签,在控制台查看元素,发现渲染出来的还是<a></a>

2.两个高亮类名

<router-link to=""></router-link>会自动给当前导航添加两个高亮类名,
分别叫:router-link-exact-activerouter-link-active
在这里插入图片描述

2.1.区别
  • router -link-active
    这个用得多,它是模糊匹配的
    如:a href="#/my"标签中有这个类,那么它将匹配所有以my开头的路径:/my /my/a /my/b
  • router-link-exact-active
    这个类是精确匹配的,写的什么就匹配什么
2.2.为什么支持模糊匹配的类用得更多?

场景:网易云音乐在"发现音乐"的一级导航栏下面还有二级导航栏:推荐,排行榜,歌单等等
此时我们对页面有一个需求,
即用户在二级菜单下来回点击的时候,一级导航栏"发现音乐"要保持高亮状态
这时候就是模糊匹配中的/my/a和/my/b情况(/FindMusic/、 /FindMusic/TopList 和/FindMusic/PlayList)
在这里插入图片描述

2.3.自定义高亮类名

这两个类名太长了,可以在router路由对象中进行定制:

//main.js或index.js
const router=new VueRouter({
	routes:[...],
	linkActiveClass:"新类名1",//比如"active"
	linkExactActiveClass:"新类名2",//比如:"exact-active"
});

效果:
在这里插入图片描述

2.4.自定义高亮类名设置样式(全局样式)

创建assets/css/global.css

/* 通过deepseek配置全局样式文件示例 */
.active {  /* 模糊匹配 */
  color: #42b983;
  position: relative;
}

.active::after {  /* 下划线动画效果 */
  content: '';
  position: absolute;
  bottom: -5px;
  left: 0;
  width: 0;
  height: 2px;
  background: #42b983;
  transition: width 0.3s;
}

.exact-active {  /* 精确匹配 */
  font-weight: 700;
  background: linear-gradient(90deg, #42b98333 0%, #ffffff 100%);
}

/* 激活状态下的动画 */
.router-link-active.active::after {
  width: 100%;
}

/*把此css文件在入口文件main.js中导入:import "@/assets/css/global.css"*/
3.跳转传参
  • 目标:在跳转路由的时候传值
  • 场景:
    在搜索栏下方的热门搜索词中,点击其中一个,会跳转到搜索该词条的结果页,即:
    这个词条就是跳转过程中所传的值
  • 方法:查询参数传参和动态路由传参
3.1.查询参数传参:在配置路径的同时进行传参
  • 语法:和地址栏传参的格式一致,故被称为查询参数传参
to="path?参书名1=参数值1&参数名2=参数值2"
  • 获取参数:对应页面的组件接受传过来的值
$route.query.参数名
  • 示例:在首页点击不同文字后跳转到搜索页,并传参
//首页:Home.vue
<!-- 第一步:路径后加?属性名和属性值键值对 -->
<router-link to="/search?key=特朗普">特朗普</router-link>
<router-link to="/search?key=中美关税">中美关税</router-link>
<router-link to="/search?key=贸易战">贸易战</router-link>

//搜索页:Search.vue
<div class="search">
	<!-- 第二步:对应页面组件接受传值 -->
	<p>搜索关键字{{$route.query.key}}</p>
	<p>搜索结果
		<ul>
			<li>...</li>
		</ul>
	</p>
</div>

/*
思考:在搜索页中什么时候和如何拿到参数?
答:在created中获取,此时要加this
created(){
	console.log(this.$route.query.key);
}
*/
  • 踩坑
    验证此例的时候出现了路由无法跳转的问题,Search页地址栏或组件显示都无效,
    原因: 错误地在App.vue注册和引入了Home页
    错误写法:<Home><Home>,正确写法:<router-view></router-view>
3.2.动态路由传参:路由不再是写死的,而是动态的
  • step1:配置动态路由
routes:[
	{
		path:"/search/:word", /*word是参数名,冒号不能省略,此时能匹配多个路径*/
		components:Search
	}
]
  • step2:配置导航链接
to="/path/参数值"
  • step3:对应页面的组件接受传过来的值
$route.params.参数名,:
$route.params.word
  • 示例
//router/index.js
routes:[
	{path:"/home",component:Home},
	{path:"/search/:word",component:Search};//step1:配置动态路由
]

//首页:Home.vue
//step2:配置导航链接
<router-link to="/search/特朗普">特朗普</router-link>
<router-link to="/search.中美关税">中美关税</router-link>
<router-link to="/search/贸易战">贸易战</router-link>

//搜索页:Search.vue
//step3:接收传值
<p>搜索关键字:{{$route.params.word}}
//同理在created中:
created(){
	console.log(this.$route.params.word);//可以从获取到的值来对搜索结果进行渲染
}
/*
注意区别:
	获取查询参数:this.$route.query.参数名
	获取动态路由参数:this.$route.query.参数名
*/

3.3.动态路由传参的可选符(?)

如果没有可选符可能会遇到的问题–
当配置路由的写法是这样的时候:

{path:"/search/:word",component:Search}

意味着必须携带参数,否则不通过传参直接进入搜索页时显示是空白的
解决方法:使用可选符(?)

{path:"/search/:word?",component:Search}

直接进入搜索页可以正常渲染,不会徐成空白

3.4.路由重定向

就是给路径A重定向为路径B,最常见的应用场景是让根路径http://localhost:8080/重定向为首页http://localhost:8080/Home
写法:

//index.js
routes:[
	//{path:"路径A",redirect:"/路径B"},
	{path:"/",redirect:"/home"},
	{path:"/home",component:Home}
]
3.5.找不到页面:404 not found Page

若用户输入的路径不在routes数组内,则会报错,这时候一般设置一个404页面,
设置的逻辑是在routes数组的最后匹配"*"路径,将除了前面的路径以外,都跳转到404页面中去

//新建文件views/NotFound.vue并在index.js中引入
//index.js
routes:[
	//{path:"路径A",redirect:"/路径B"},
	{path:"/",redirect:"/home"},
	{path:"/home",component:Home},
	{path:"/search",component:Search},
	{path:"*",component:NotFound}
]

六.编程式导航

1.什么是编程式导航

编程式导航通过JS控制页面跳转,和声明式导航不同,它不依赖模板语法,而是通过调用路由实例的API实现动态导航,
本质是运行时逻辑控制的路由切换

2.路由跳转
2.1.path路径跳转
//Home.vue
//html
<input type="text"><button @click="handleSearch">搜索一下</button>
//js
methods:{
	handleSearch(){
		//简写:
		//this.$router.push("/search");
		//详写:
		this.$router.push({
			path:"/search"
		});
	}
}
2.2.命名路由跳转
//router/index.js
routes:[
	{path:"/home",component:Home},
	{name:"searchPage",path:"/search",component:Search},//给路由命名
	]
//Home.vue
handleClick(){
	this.$router.push({
		name:"searchPage"
	})
}
3.路由传参

声明式导航有两种传参方式:

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

这两种方式在编程式路由中也可使用

3.1.path路径跳转+查询参数传参
//Home.vue
//html
<input type="text" v-model="inpValue"><button @click="handleSearch"></button>
//js
data{}{return{ inpValue:""}},
methods:{
	handleSearch(){
		this.$router.push({//注意:父组件是通过$router传参,...
			path:"/search",
			query:{
				//参数名1=参数值1
				key:`${this.inpValue}`
			}
	});
	}
}
//Search.vue
<p>搜索词:{{$route.query.key}}</p>//...而子组件是通过$route来接收的
3.2.path路径跳转+动态路由传参
//router/index.js
routes:[
		{path:"/search/:word",component:"Search"}//参数名--设置动态路由
	]
//Home.vue
handleSearch(){
	this.$router.push({
		path:`/search/${this.inpValue}`,//参数值
	});
}
//Search.vue
<p>搜索词:{{$route.params.word}}</p>
3.3.命名路由跳转+查询参数传参
//router/index.js
routes:[
		{name:"searchPage",path:"/search",component:Search},//命名路由
	]
//Home.vue
handleClick(){
	this.$router.push({
		name:"searchPage",
		query:{
			//参数名1:参数值1
			key:`${this.inpValue}`
		}
	});
}
//Search.vue
<p>搜索词:{{$route.query.key}}</p>
3.4.命名路由跳转+动态路由传参
//router/index.js
routes:[
		{name:"searchPage",path:"/search/:word",component:Search},//参数名---命名路由+动态路由
	]
//Home.vue
handleClick(){
	this.$router.push({
		name:"searchPage",
		params:{
			//参数名1:参数值1
			key:`${this.inpValue}`
		}
	});
}
//Search.vue
<p>搜索词:{{$route.params.word}}</p>

七.其他

1.$router实例$route对象的区别
特性$router(路由实例)$route(当前路由对象)
本质VueRouter的全局实例对象,整个应用仅有唯一一个当前激活路由的状态信息(每个路由独享)
主要作用路由操作(跳转,前进,后退)路由信息获取(路径,参数,查询字符串等)
访问方式this.$routerthis.$route
数据特性包含操作方法,如:push,go包含响应式属性,如:path,query
类比关系类似导航系统(控制方向)类似GPS定位(显示当前位置信息)
2.查询参数传参动态路由传参的优劣
特性查询参数传参(query)动态路由传参(params)
URL表现形式/user/123 路径参数/search?keyword=vue&page=1(URL查询字符串)
路由配置要求必须预先定义动态路由,如:path:'/user/:id'无需特殊路由配置
参数可见性参数直接暴露在路径中参数显示在URL的?之后
参数类型始终为字符串(需要手动类型转换)始终为字符串(需要手动类型转换)
参数必要性通常是必填参数(如资源ID)常用于可选参数(如过滤条件,分页等)
浏览器历史记录完全不同的URL会被视为新纪录同一路径不同查询参数会被视为同一个路由
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端OnTheRun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值