文章目录
1、安装
- 在项目集成终端中打开 输入:
npm i vue-router
- 根据项目需要可以选择安装,默认安装为最高版本 @3:vue2 @4:vue3
- 在Vue的 packge.json 可以查看是否安装成功以及版本号
2、使用
2.1、导入路由
在src 创建一个名为 router 的文件夹,并且创建一个js
导入路由,并制作成全局对象
代码如下(示例):
// 导入路由
import VueRouter from "vue-router";
import Vue from "vue";
Vue.use(VueRouter)
2.2、 创建
页面的vue 我们一般放中 src文件下的views
文件下
- 创建路由数组 routes 组成
- 一个路由对象就表示的是一个页面
- 引入创建好的 vue 文件
‘/’
一般为页面的首页‘/xxx’
一般为页面的其他页面
// 导入创建的vue 项目
import Home from '../views/HomeView.vue';
import About from '../views/AboutViem.vue';
Vue.use(VueRouter)
// 创建路由
// 创建路由数组 routes
// 一个路由对象就表示的是一个页面
const routes = [
// / 地址表示的是 服务器地址 http://localhost:8080
{
path: '/', // 页面地址
component: Home// 页面组件
},
{
path: '/about',
component: About
}
]
2.3、创建路由实例
根据使写和的路由数组创建路由实例
- history 完全模拟浏览器的历史
- hash 利用的锚点跳转 地址栏会有 #
const router = new VueRouter({
router,
mode: 'history'
// 路由模式
// (history 完全模拟浏览器的历史)
// (hash 利用的锚点跳转 地址栏会有 #)
})
2.3、导出
在 main.js 中的router
名字相同时才能简写,不同时需要写成 router:xxxx
2.4、使用
- 在app.vue中导入
<router-view />
- 展示对应的路由
- 当页面地址和路由数组内的某个路由的 path 匹配的时候就展示对应的路由的组件
<template>
<div>
<h2>router 的使用</h2>
<router-view /> *****
</div>
</template>
<script>
export default {};
</script>
<style>
</style>
2.5、使用router-link 完成切换
- to = “地址位置”
2.6、介绍
2.6.1、to
- 类型: string | Location
- required
- 表示目标路由的链接。当被点击后,内部会立刻把 to 的值传到
router.push()
,所以这个值可以是一个字符串或者是描述目标位置的对象。 - path 指的是地址
query: 是地址的查询部分:?type=completed
下面的结果为 /about?type=completed&a=hello
<router-link :to="{path:'/about', query:{type: 'complete',a: 'hello'}}" active-class="active">About</router-link>
2.6.2、active-class
- 类型: string
- 默认值: “router-link-active”
- 设置链接激活时使用的 CSS 类名。默认值可以通过路由的构造选项 linkActiveClass 来全局配置。
- 当只使用它来改变颜色的时候 因为 都包含了 ‘/ ’,会无法区分,这时候需要精确匹配
exact
2.6.3、exact
- 类型: boolean
- 默认值: false
- 作用 严格匹配
active-class与exact 的使用例子
2.6.4、使用children实现页面的显示
- 对于home 内的页面叫子页面,子路由 只有在home 页面出现的时候子路由才能出现
- 需要设置到 Home 路由的 children 属性内
- home 里面有三个子页面,但样子相同只是数据不同,使用使用一个组件表示
- 子路由开头不能写
/
- 使用
<router-view />
则显示子
// 导入路由
import Posts from '../views/PostsViem.vue'
const routes = [
。。。。
{
path: '/', // 页面地址
component: Home, // 页面组件
// 对于home 内的页面叫子页面,子路由 只有在home 页面出现的时候子路由才能出现
// 需要设置到 Home 路由的 children 属性内
// home 里面有三个子页面,但样子相同只是数据不同,使用使用一个组件表示
// 子路由开头不能写 /
children: [
{
path: ':type',
component: Posts
}
]
},
]
- 使用 active-class 进行页面的区分
<template>
<div>
<router-link active-class="active" >综合</router-link>
<span> | </span>
<router-link active-class="active" >前端</router-link>
<span> | </span>
<router-link active-class="active" >后端</router-link>
</template>
<script>
export default {
}
</script>
<style scoped>
.home-nav a{
color: #000;
text-decoration: none;
}
.home-nav .active {
color: blue;
}
</style>
其中我们也可以设置默认子路由
- 当页在Home 页面时直接展示 内容
children: [
// 默认子路
{
path: '',// 不写内容,因为父路由 匹配的时候将自动展示 Posts 的页面
component: Posts
},
{
path: ':type',
component: Posts
}
- 但这个样子有一个问题
- 当我们在 Home 中点击 综合后 Home 的点击颜色不见了
2.6.5、使用 this.$route 去解决 2.6.4的问题
- 当地址为 综合、前端、后端 页面的时候 home 导航也需要改变颜色,路由提供的导航激活样式是没有办法实现这个功能的
- 我们需要自己写class 去实现这个功能
- 当路由的动作是
’/‘
或/recommended /fronted /backend
的时候变色 - 在组件中想要获取当前地址的话 需要使用路由提供的 路由对象
this.$route
去实现
<router-link to="/" :class="{active: ['/recommended','/frontend','/baclend','/'].includes($route.path)}">Home</router-link>
<router-link :class="{active: $route.path === '/' || $route.path === '/recommended'}" to="/recommended">综合</router-link>
2.6.6、根据 综合、前端、后端展示不同的内容
- 展示文章列表需要知道展示哪个类别的文章
- 类别只能在当然地址栏有信息 就是动态路由参数 type
<div>
文章列表{{ $route.params.type || "recommended"}}
</div>
- 动态路由展示的就是一个组件,当动态路由之间来回切换的时候 组件是不会重新渲染的,所以 created 只能执行一次
-
- 我们可以选择使用 侦听器来监听 params 的动作
<script>
export default {
created() {
const type = this.$route.params.type || "recommended"
console.log('发请求',type)
}
}
</script>
- 解决 方案 使用 watch
<script>
export default {
watch: {
"$route.params": {
handler(){
const type = this.$route.params.type || "recommended"
console.log('发请求',type)
},
immediate: true // 一开始就执行
}
}
}
</script>
2.6.6、获取后端数据
-
先在项目集成终端中输入 :
npm i axios
安装 axios 工具包括 -
获取
http://jsonplaceholder.typicode.com/posts
的数组内容
<script>
import axios from 'axios' // 导入 axios
export default {
data() {
return {
posts: [], // 创建一个空的数组
}
},
watch: {
"$route.params": {
async handler() {
const type = this.$route.params.type || "recommended";
// 当 type 为谁获取到的内容
// /recommended userId: 1
// /frontend userId: 2
// /baclend userId: 3
const typeNum = type === 'recommended' ? 1 : type === 'frontend' ? 2 : 3;
const res = await axios.get(`http://jsonplaceholder.typicode.com/posts?userId=${typeNum}`);
console.log(res.data)
},
immediate: true, // 一开始就执行
},
},
};
</script>
- 展示到前端
<ul v-if="posts.length">
<li v-for="post in posts" :key="post.id">{{post.title}}</li>
</ul>
2.6.7、获取标题内的详情内容 以 props
我们可以通过动态的id 去获取内容
import Post from '../views/PostView.vue'
Vue.use(VueRouter)
// 创建路由
// 创建路由数组 routes
// 一个路由对象就表示的是一个页面
const routes = [
{
path: '/about',
component: About
},
// / 地址表示的是 服务器地址 http://localhost:8080
{
path: '/post/:postId',// 根据id 的不同去展示不同的信息
component: Post
},
- 使用 router-link 确认位置
<ul v-if="posts.length">
<li v-for="post in posts" :key="post.id">
<router-link :to='`/post/${post.id}`'>
{{post.title}}
</router-link>
</li>
</ul>
-
根据id 展示不同的文章
-
也可采用另外一种写作法
-
可以使用 props 给路由组件传参,直接 true 将路由的动态参数当作 props 传递给组件
-
添加一个等待效果,防止页面信息串流
<!-- 等待效果图 -->
<div v-else>
<img src="../assets/351b23dd358cae9bb10aa2e39036d86c.gif" alt="">
</div>
watch: {
"$route.params": {
async handler() {
。。。。
// 切换请求之间清空内容
this.posts = []
。。。。。
},
immediate: true, // 一开始就执行
},
},
2.6.8、编程式导航
- 不使用router-link 进行跳转到首页
- 首先需要绑定点击事件
Vue
路由提供了$router
来获取整个路由 可以实现路由的跳转push
跳转back
返回上一级
<template>
<div v-if="post">
<button @click="goHome">文章详情</button> <!-- 创建点击事件 -->
<h3>{{ post.title }}</h3>
<p>{{ post.body }}</p>
</div>
</template>
<script>
import axios from "axios";
export default {
。。。。。
methods: {
goHome() {
// 不使用 routelink 跳转
// 编程式导航
// vue 路由提供了 $router 来获取整个路由 可以实现路由的跳转
this.$route.push('/')
// push跳转 back 返回上一级
}
}
};
</script>
2.6.9、也可以使用name 进行跳转
- 当父路由有默认子路由的时候 name 必须写在子路由上
- 不然会报错,并且无法展示信息
当没写在子路由上时的错误提示
网页别名与重定向
当网站更新网站地址的时候,一些老用户还是使用原来的地址,如何解决访问的问题就需要用到别名或重定向
- 将 /about 改为 /xxx 还是可以正常访问
2.7、路由的懒加载
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
- 对于以前的写法 先导入 在使用,会导致页面还没有出现的时候就解析了 组件 浪费了 应用内存
先导入 在使用 ,还没有出现的 时候就会解析 浪费 应用内存
import About from '../views/AboutViem.vue'
Vue.use(VueRouter)
{
path: '/about',
component: About,
alias: '/xxx'
},
- 解决方法:
- 换成懒加载模式使用组件
{
path: '/about',
component: ()=> import('../views/AboutViem.vue'),
alias: '/xxx'
},
- 作用:
- 节约内存
- 在第一次使用页面的时候加载更快
- 除了首页
‘/’
其他的页面都建议使用懒加载以至加快速度,增加用户体验。
2.8、过渡动画
在页面与页面之间的切换的时候我们可以使用 transition
去包裹 <router-view />
然后创建动画效果
具体内容参考 过渡与动画
<transition name="move" mode="poy-in">
<router-view />
</transition>
<style>
.move-enter {
transform: translateX(100px);
opacity: 0;
}
.move-leave-to {
transform: translateX(-100px);
opacity: 0;
}
.move-enter-active, .move-leave-active {
transition: all .5s;
}
</style>
2.9、导航守卫
正如其名,vue-router
提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。
记住参数或查询的改变并不会触发进入/离开的导航守卫。你可以通过观察 $route
对象来应对这些变化,或使用 beforeRouteUpdate
的组件内守卫。
- 在创建路由实例与导出的中间插入导航守卫
- 对于然后的路由跳转都是会触发全局守卫的
- 全局前置守卫
router.beforeEach((to, from, next) => {
})
- to 要去那
- from 从那里来
- next() 放不放行
- 对于全局前置守卫里面必须使用 next 来放行,否则是不会展示其页面的内容的
- 对于前置守卫的 next 我们可以实现强制的登陆功能,如果没有登陆则无法进入应用内容页类似于 QQ、微信
- 这时我们的结构就变成了
- LoginView.vue 为登陆
- MainViem.vue 内容页面
- App.vue 使用
<router-view />
展示内容
在这里的时候我们的页面还是可以正常展示
2.9.1、登录功能的实现
-
我们要实现一个登陆的效果,
-
第一点 我们写的内容 在没有登陆的时候是无法登陆页面之外的其他所有页面
-
第二点 其他的页面就需要知道 是否登录了的信息,登录了就可以进入内容信息页,没登录之前去登录页面
-
第三点 可以在全局前置守卫里面获取登录的状态,登录了 就可以进入到其他页面,没到了就到登录页面
-
对于 localStorage 与 sessionStorage 的区别
- 1)localStorage 是永久存储就算你关闭了网站在重新打开网站,登录信息依然存在
- 2)sessionStorage 是临时存储当关闭了网站 登录信息就会清空,需要重新输入用户名密码
-
localStorage 与 sessionStorage 用法是一样的只是存储方式不同
-
对于存储的值会默认被转换成字符串
-
也就是说 对象类型是无法存储的
-
但可以通过将对象类型转换为 json 串,在存储,取的时候在转换成对象
2.9.2、退出功能的实现
- 回到登录页面
- 清除登录状态,用的 localStorage 或 sessionStorage 谁的方法就用谁清除
2.、总结
-
1)安装
-
nmp i vue-router
- vue2对应安装的版本是
vue-router3
- vue2对应安装的版本是
-
2)创建
-
3)使用
-
需要注意
- router-link 跳转
- router-view 展示
- $route 当前路由地址
- $router 整个路由信息,可以做跳转,回退