一、单页应用程序介绍
1.概念
单页应用程序:SPA【Single Page Application】是指所有的功能都在一个html页面上实现
2.具体示例
单页应用网站: 网易云音乐 网易云音乐
多页应用网站:京东 京东(JD.COM)-正品低价、品质保障、配送及时、轻松购物!
3.单页应用 VS 多页面应用
优势
-
传统的多页面应用程序,每次请求服务器返回的都是一整个完整的页面
-
单页面应用程序只有第一次会加载完整的页面
-
以后每次请求仅仅获取必要的数据,减少了请求体积,加快页面响应速度,降低了对服务器的压力
-
SPA更好的用户体验,运行更加流畅
缺点
-
开发成本高 (需要学习路由)
vue-router
-
不利于 SEO 搜索引擎优化 谷歌浏览器在解决这个问题 ssr:服务端渲染 server side rendering
应用:
单页应用类网站:系统类网站 / 内部网站 / 文档类网站 / 移动端站点
多页应用类网站:公司官网 / 电商类网站
二、路由介绍
1.思考
单页面应用程序,之所以开发效率高,性能好,用户体验好
最大的原因就是:页面按需更新
比如当点击【发现音乐】和【关注】时,只是更新下面部分内容,对于头部是不更新的
要按需更新,首先就需要明确:访问路径和 组件的对应关系!
访问路径 和 组件的对应关系如何确定呢? 路由
2.路由的介绍
生活中的路由:设备和ip的映射关系
Vue中的路由:路径和组件的映射关系
三、路由的基本使用
1.目标
认识插件 VueRouter,掌握 VueRouter 的基本使用步骤
2.作用
修改地址栏路径时,切换显示匹配的组件
3.说明
Vue 官方的一个路由插件,是一个第三方包
4.官网
5.VueRouter的使用
固定5个固定的步骤(不用死背,熟能生巧)
-
下载 VueRouter 模块到当前工程,版本3.6.5
yarn add vue-router@3.6.5
-
main.js中引入VueRouter
import VueRouter from 'vue-router'
-
安装注册
Vue.use(VueRouter)
-
创建路由对象,配置路由规则,并且注入到Vue实例中
const router = new VueRouter({ routes:[ {path:'/xxx',component:xxxx}, .... ] }) new Vue({ render: h => h(App), router }).$mount('#app')
-
配置路由出口
<router-view></router-view>
6.代码示例
App.vue
<template>
<div>
<div class="footer_wrap">
<a href="#/find">发现音乐</a>
<a href="#/my">我的音乐</a>
<a href="#/friend">朋友</a>
</div>
<div class="top">
</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文件分2类, 一个是页面组件, 一个是复用组件
.vue文件本质无区别, 方便大家学习和理解, 总结的一个经验
src/views(或pages) 文件夹 和 src/components文件夹
-
页面组件 - 页面展示 - 配合路由用
-
复用组件 - 展示数据/常用于复用
创建组件
// 4. 创建一个路由对象
const router = new VueRouter({
// 路由的规则
// route: 一条路由规则
routes: [
{
// 路径 锚点
// 组件
path: '/find',
component: Find,
},
{
path: '/my',
component: My,
},
{
path: '/friend',
component: Friend,
},
],
})
==必须指定路由的出口==
<div class="top">
<!-- 路由的出口 -->
<router-view></router-view>
</div>
路由的封装
新建文件router/index.js
import Vue from 'vue'
// 2. 导入VueRouter
import VueRouter from 'vue-router'
import Find from '../views/Find'
import My from '../views/My'
import Friend from '../views/Friend'
// 3. 使用vue插件 vue的插件想要生效必须调用一个方法 Vue.use(XXXX)
Vue.use(VueRouter)
// 4. 创建一个路由对象
const router = new VueRouter({
// 路由的规则
// route: 一条路由规则
routes: [
{
// 路径 锚点
// 组件
path: '/find',
component: Find,
},
{
path: '/my',
component: My,
},
{
path: '/friend',
component: Friend,
},
],
})
export default router
main.js中
import router from './router'
new Vue({
// 5. 关联路由对象和vue实例 data methods
render: (h) => h(App),
router,
}).$mount('#app')
五、vue路由 - 声明式导航
5.1 声明式导航 - 基础使用
目标: 可用全局组件router-link来替代a标签
-
vue-router提供了一个全局组件 router-link
-
router-link实质上最终会渲染成a链接 to属性等价于提供 href属性(to无需#)
-
router-link提供了声明式导航高亮的功能(自带类名)
<template>
<div>
<div class="footer_wrap">
<router-link to="/find">发现音乐</router-link>
<router-link to="/my">我的音乐</router-link>
<router-link to="/part">朋友</router-link>
</div>
<div class="top">
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {};
</script>
<style scoped>
/* 省略了 其他样式 */
.router-link-exact-active,
.router-link-active {
background-color: #555 !important;
}
</style>
总结: 链接导航, 用router-link配合to, 实现点击切换路由
5.2 导航高亮
RouterLink会自动给当前导航添加两个类名
<!--
RouterLink会自动给当前的链接添加两个类名
router-link-active: 激活的导航链接 模糊匹配
router-link-exact-active: 激活的导航链接 精确匹配
exact: 必须要精确匹配
-->
<RouterLink to="/" exact>发现音乐</RouterLink>
<RouterLink to="/my">我的音乐</RouterLink>
<RouterLink to="/friend">朋友</RouterLink>
可以修改默认高亮的类名
const router = new VueRouter({
linkActiveClass: 'aa',
linkExactActiveClass: 'aa',
// route: 一条规则
}
5.3 声明式导航 - 跳转传参
目标: 在跳转路由时, 可以给路由对应的组件内传值
在router-link上的to属性传值, 语法格式如下
-
/path?参数名=值
-
/path/:id – 需要路由对象提前配置 path: “/path/参数名”
对应页面组件接收传递过来的值
-
$route.query.参数名
-
$route.params.参数名
-
创建views/Part.vue - 准备接收路由上传递的参数和值
<template> <div> <p>关注明星</p> <p>发现精彩</p> <p>寻找伙伴</p> <p>加入我们</p> <p>人名: {{ $route.query.name }} -- {{ $route.params.username }}</p> </div> </template>
-
路由定义
{ path: "/part", component: Part }, { path: "/part/:username", // 有:的路径代表要接收具体的值 component: Part },
-
导航跳转, 传值给MyGoods.vue组件
<router-link to="/part?name=小传">朋友-小传</router-link> <router-link to="/part/小智">朋友-小智</router-link>
六、vue路由 - 重定向和模式
6.1 路由 - 重定向
目标: 匹配path后, 强制切换到目标path上
-
网页打开url默认hash值是/路径
-
redirect是设置要重定向到哪个路由路径
例如: 网页默认打开, 匹配路由"/", 强制切换到"/find"上
const routes = [
{
path: "/", // 默认hash值路径
redirect: "/find" // 重定向到/find
// 浏览器url中#后的路径被改变成/find-重新匹配数组规则
}
]
总结: 强制重定向后, 还会重新来数组里匹配一次规则
6.2 路由 - 404页面
目标: 如果路由hash值, 没有和数组里规则匹配
默认给一个404页面
语法: 路由最后, path匹配*(任意路径) – 前面不匹配就命中最后这个, 显示对应组件页面
-
创建NotFound页面
<template> <img src="../assets/404.png" alt=""> </template> <script> export default { } </script> <style scoped> img{ width: 100%; } </style>
-
在main.js - 修改路由配置
import NotFound from '@/views/NotFound' const routes = [ // ...省略了其他配置 // 404在最后(规则是从前往后逐个比较path) { path: "*", component: NotFound } ]
总结: 如果路由未命中任何规则, 给出一个兜底的404页面
6.3 路由 - 模式设置
目标: 修改路由在地址栏的模式
hash路由例如: http://localhost:8080/#/home
history路由例如: http://localhost:8080/home (以后上线需要服务器端支持)
router/index.js
const router = new VueRouter({
routes,
mode: "history" // 打包上线后需要后台支持, 模式是hash
})
七、vue路由 - 编程式导航
编程式导航用JS代码跳转
声明式导航用a标签
7.1 编程式导航 - 基础使用
目标: 用JS代码来进行跳转
语法:
this.$router.push({
path: "路由路径", // 都去 router/index.js定义
name: "路由名"
})
-
main.js - 路由数组里, 给路由起名字
{
path: "/find",
name: "Find",
component: Find
},
{
path: "/my",
name: "My",
component: My
},
{
path: "/part",
name: "Part",
component: Part
},
-
App.vue - 换成span 配合js的编程式导航跳转
<template>
<div>
<div class="footer_wrap">
<span @click="btn('/find', 'Find')">发现音乐</span>
<span @click="btn('/my', 'My')">我的音乐</span>
<span @click="btn('/part', 'Part')">朋友</span>
</div>
<div class="top">
<router-view></router-view>
</div>
</div>
</template>
<script>
// 目标: 编程式导航 - js方式跳转路由
// 语法:
// this.$router.push({path: "路由路径"})
// this.$router.push({name: "路由名"})
// 注意:
// 虽然用name跳转, 但是url的hash值还是切换path路径值
// 场景:
// 方便修改: name路由名(在页面上看不见随便定义)
// path可以在url的hash值看到(尽量符合组内规范)
export default {
methods: {
btn(targetPath, targetName){
// 方式1: path跳转
this.$router.push({
// path: targetPath,
name: targetName
})
}
}
};
</script>
7.2 编程式导航 - 跳转传参
目标: JS跳转路由, 传参
语法 query / params 任选 一个
this.$router.push({
path: "路由路径"
name: "路由名",
query: {
"参数名": 值
}
params: {
"参数名": 值
}
})
// 对应路由接收 $route.params.参数名 取值 // 对应路由接收 $route.query.参数名 取值
==格外注意: 使用path会自动忽略params==
App.vue
<template>
<div>
<div class="footer_wrap">
<span @click="btn('/find', 'Find')">发现音乐</span>
<span @click="btn('/my', 'My')">我的音乐</span>
<span @click="oneBtn">朋友-小传</span>
<span @click="twoBtn">朋友-小智</span>
</div>
<div class="top">
<router-view></router-view>
</div>
</div>
</template>
<script>
// 目标: 编程式导航 - 跳转路由传参
// 方式1:
// params => $route.params.参数名
// 方式2:
// query => $route.query.参数名
// 重要: path会自动忽略params
// 推荐: name+query方式传参
// 注意: 如果当前url上"hash值和?参数"与你要跳转到的"hash值和?参数"一致, 爆出冗余导航的问题, 不会跳转路由
export default {
methods: {
btn(targetPath, targetName){
// 方式1: path跳转
this.$router.push({
// path: targetPath,
name: targetName
})
},
oneBtn(){
this.$router.push({
name: 'Part',
params: {
username: '小传'
}
})
},
twoBtn(){
this.$router.push({
name: 'Part',
query: {
name: '小智'
}
})
}
}
};
</script>