SPA应用的理解
单页面的应用(single page web application , SPA)
整个项目 只有一个完整的页面
点击页面中的 导航 不会导致页面的刷新,只有做页面的局部刷新
数据需要通过异步请求获取
路由
什么是路由 一个路由就是一组映射关系(key-value)
key:是路径 , value:function component (函数、组件)
前端路由
value component (组件) 用于显示页面的内容
后端路由
value function (函数) 用于处理用户端提交的请求
r o u t e 和 route和 route和router的区别详解
$ router是用来操作路由的,$ route是用来获取路由信息的。
-
$router是VueRouter的一个实例,他包含了所有的路由,包括路由的跳转方法,钩子函数等,也包含一些子对象(例如history)
-
$ route是一个跳转的路由对象(路由信息对象),每一个路由都会有一个$route对象,是一个局部的对象。
-
-
主要属性
- $route.path 字符串,等于当前路由对象的路径,会被解析为绝对路径,如/home/ews
- $route.params 对象,包含路由中的动态片段和全匹配片段的键值对,不会拼接到路由的url后面
- $route.query 对象,包含路由中查询参数的键值对。会拼接到路由url后面
- $route.router 路由规则所属的路由器
- $route.name 当前路由的名字,如果没有使用具体路径,则名字为空
-
使用步骤
基本使用
- 安装vue-router npm i vue-router@3.2.0
- 在 src 目录下创建 index.js 文件
- 在main.js 中
- 导入
- import VueRouter from “vue-router”;
import router from “./router”;
- import VueRouter from “vue-router”;
- 应用插件
- Vue.use(VueRouter)
- 在Vue 创建实例中添加 router 属性
- new Vue({
// render: h => h(App),
// 完整的写法
render(createElement){
return createElement(App)
},
store,
router
}).$mount(’#app’)
- new Vue({
- 导入
- 在 router / index.js 文件中
- 引入VueRouter
- import VueRouter from “vue-router”;
- 导入组件
- import About from “@/components/About”;
import Home from “@/components/Home”;
- import About from “@/components/About”;
- 创建 并 暴露 router实例对象,去管理一组一组的路由规则
- export default new VueRouter({
routes:[
{
path:’/被请求的路径’,
component: 引入组件的名称****_ **},
{
path: ‘/home’,
component: **Home
_**}
]
})
- export default new VueRouter({
- 引入VueRouter
- 在App.vue 中注册
- 指定组件显示的位置
- 触发路由的跳转 这个标签 效果 相当于a标签
About
- 指定组件显示的位置
案例
<template>
<div>
<h2>我是About组件的内容</h2>
</div>
</template>
<script>
export default {
name: "About"
}
</script>
<style scoped>
</style>
<template>
<div>
<h2>我是Home组件的内容</h2>
</div>
</template>
<script>
export default {
name: "Home"
}
</script>
<style scoped>
</style>
import VueRouter from "vue-router";
// 引入 组件
import About from "@/components/About";
import Home from "@/components/Home";
// 创建 并 暴露 router实例对象,去管理一组一组的路由规则
export default new VueRouter({
routes:[
{
// path /被请求的路径
path:'/about',
// 引入组件的名称
component: About
},
{
path: '/home',
component: Home
}
]
})
import Vue from 'vue'
import App from './App.vue'
import store from "./store";
import VueRouter from "vue-router";
import router from "./router";
Vue.config.productionTip = false
Vue.use(VueRouter)
new Vue({
// render: h => h(App),
// 完整的写法
render(createElement){
return createElement(App)
},
store,
router
}).$mount('#app')
<template>
<div id="app">
<div class="row">
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header">
<h2>VUE 路由 案例</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!-- 原始的HTML 实现页面的跳转 -->
<!-- <a class="list-group-item active" href="./about.html">About</a>
<a class="list-group-item active" href="./home.html">Home</a>-->
<!-- 在VUE中借助router-link 实现路由的切换 -->
<router-link class="list-group-item active" to="/about">
About
</router-link>
<router-link class="list-group-item active" to="/home">
Home
</router-link>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<!-- 指定组件的展示位置 -->
<router-view></router-view>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'App',
components: {}
}
</script>
<style scoped>
</style>
命名路由
作用:简化路由的跳转路径
命名
{name:‘xq’,
path: ‘detail/:id/:title’,
component: Detail}
使用
多级路由
- 配置路由规则,使用 children 配置项
- {
path: ‘/home’,
component: Home,
children:[
{
path:‘news’,
component: News
_ _}
]
}
- {
- 触发路由的跳转(要写完整路径)
{{ m.title }}
- 指定组件显示的位置
注意: 子路径前不加 “/” 跳转时 需要写完整路径 /home/news
案例
<template>
<div>
<h2>我是About组件的内容</h2>
</div>
</template>
<script>
export default {
name: "About"
}
</script>
<style scoped>
</style>
<template>
<div>
<h2>我是Home组件的内容</h2>
<div>
<ul class="nav nav-tabs">
<li>
<router-link class="list-group-item" active-class="active" to="/home/news">
News
</router-link>
</li>
<li>
<router-link class="list-group-item" active-class="active" to="/home/message">
Message
</router-link>
</li>
</ul>
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: "Home"
}
</script>
<style scoped>
</style>
<template>
<ul>
<li>news001<input/></li>
<li>news002<input/></li>
<li>news003<input/></li>
</ul>
</template>
<script>
export default {
name: "News"
}
</script>
<style scoped>
</style>
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
{{ m.title }}
</li>
</ul>
<hr/>
</div>
</template>
<script>
export default {
name: "Message",,
data(){
return{
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'}
]
}
}
}
</script>
<style scoped>
</style>
import VueRouter from "vue-router";
import About from "@/components/About";
import Home from "@/components/Home";
import News from "@/components/News";
import Message from "@/components/Message";
import Detail from "@/components/Detail";
const router = new VueRouter({
routes:[
{
path:'/about',
component:About,
},
{
path:'/home',
component:Home,
children:[ //通过children配置子级路由
{
path:'news', //此处一定不要写:/news
component:News
},
{
path:'message',//此处一定不要写:/message
component:Message
}
]
}
]
})
export default router;
import Vue from 'vue'
import App from './App.vue'
import store from "./store";
import VueRouter from "vue-router";
import router from "./router";
Vue.config.productionTip = false
Vue.use(VueRouter)
new Vue({
// render: h => h(App),
// 完整的写法
render(createElement){
return createElement(App)
},
store,
router
}).$mount('#app')
<template>
<div id="app">
<div class="row">
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header">
<h2>Vue 路由案例</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!-- 原始的HTML 实现页面的跳转 -->
<!-- <a class="list-group-item active" href="./about">About</a>-->
<!-- <a class="list-group-item active" href="./home">Home</a>-->
<!-- 在Vue中借助router-link 实现路由的切换 -->
<router-link class="list-group-item active" to="/about">
About
</router-link>
<router-link class="list-group-item active" to="/home">
Home
</router-link>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<!-- 指定组件的展示位置-->
<router-view></router-view>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style>
</style>
传参
query参数 传递
- 传递参数
- 路由并携带query参数 字符串
{{ m.title }}
- 路由并携带query参数 对象
{{ m.title }}
- 路由并携带query参数 字符串
- 接收参数
- $route.query.参数名
- {{$route.query.id}}
- {{$route.query.id}}
- $route.query.参数名
案例
<template>
<div>
<h2>我是About组件的内容</h2>
</div>
</template>
<script>
export default {
name: "About"
}
</script>
<style scoped>
</style>
<template>
<div>
<h2>我是Home组件的内容</h2>
<div>
<ul class="nav nav-tabs">
<li>
<router-link class="list-group-item" active-class="active" to="/home/news">
News
</router-link>
</li>
<li>
<router-link class="list-group-item" active-class="active" to="/home/message">
Message
</router-link>
</li>
</ul>
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: "Home"
}
</script>
<style scoped>
</style>
<template>
<ul>
<li>news001<input/></li>
<li>news002<input/></li>
<li>news003<input/></li>
</ul>
</template>
<script>
export default {
name: "News"
}
</script>
<style scoped>
</style>
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<!-- 路由 并 携带query 参数 字符串 -->
<!-- <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">
{{ m.title }}
</router-link>-->
<!-- 路由 并 携带query 参数 对象 -->
<router-link :to="{
path:'/home/message/detail',
query:{
id: m.id,
title: m.title
}
}">
{{ m.title }}
</router-link>
<!-- query: 通过路由的name属性 简化请求路径-->
<!-- <router-link :to="{
name: 'xq',
query:{
id: m.id,
title: m.title
}
}">
{{ m.title }}
</router-link>-->
</li>
<input/>
</ul>
<hr/>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "Message",
data(){
return{
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'}
]
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<ul>
<li>
消息编号:{{$route.query.id}}
</li>
<li>
消息标题:{{$route.query.id}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: "Detail"
}
</script>
<style scoped>
</style>
import VueRouter from "vue-router";
import About from "@/components/About";
import Home from "@/components/Home";
import News from "@/components/News";
import Message from "@/components/Message";
import Detail from "@/components/Detail";
const router = new VueRouter({
routes:[
{
path:'/about',
component: About
},
{
path: '/home',
component: Home,
children:[
{
path:'news',
component: News
},
{
path: 'message',
component: Message,
children: [
{
name:'xq',
path: 'detail',
component: Detail,
}
]
}
]
}
]
})
export default router;
import Vue from 'vue'
import App from './App.vue'
import store from "./store";
import VueRouter from "vue-router";
import router from "./router";
Vue.config.productionTip = false
Vue.use(VueRouter)
new Vue({
// render: h => h(App),
// 完整的写法
render(createElement){
return createElement(App)
},
store,
router
}).$mount('#app')
<template>
<div id="app">
<div class="row">
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header">
<h2>Vue 路由案例</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!-- 原始的HTML 实现页面的跳转 -->
<!-- <a class="list-group-item active" href="./about">About</a>-->
<!-- <a class="list-group-item active" href="./home">Home</a>-->
<!-- 在Vue中借助router-link 实现路由的切换 -->
<router-link class="list-group-item active" to="/about">
About
</router-link>
<router-link class="list-group-item active" to="/home">
Home
</router-link>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<!-- 指定组件的展示位置-->
<router-view></router-view>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style>
</style>
params参数传递
需要在路由配置文件中,在路由后面加上占位符
- index.js 中的 path中使用 /:参数名/:参数名…
- path: ‘detail/:id/:title’
- 传参
{{ m.title }}
- 使用 {{$route.params.参数名}}
- {{$route.params.id}}
特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置!
案例
<template>
<div>
<h2>我是About组件的内容</h2>
</div>
</template>
<script>
export default {
name: "About"
}
</script>
<style scoped>
</style>
<template>
<div>
<h2>我是Home组件的内容</h2>
<div>
<ul class="nav nav-tabs">
<li>
<router-link class="list-group-item" active-class="active" to="/home/news">
News
</router-link>
</li>
<li>
<router-link class="list-group-item" active-class="active" to="/home/message">
Message
</router-link>
</li>
</ul>
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: "Home"
}
</script>
<style scoped>
</style>
<template>
<ul>
<li>news001<input/></li>
<li>news002<input/></li>
<li>news003<input/></li>
</ul>
</template>
<script>
export default {
name: "News"
}
</script>
<style scoped>
</style>
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<!-- params 传参-->
<router-link :to="{
name: 'xq',
params: {
id: m.id,
title: m.title
}
}">
{{ m.title }}
</router-link>
</li>
<input/>
</ul>
<hr/>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "Message",
data(){
return{
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'}
]
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<ul>
<li>
消息编号:{{$route.params.id}}
</li>
<li>
消息标题:{{$route.params.id}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: "Detail"
}
</script>
<style scoped>
</style>
import VueRouter from "vue-router";
import About from "@/components/About";
import Home from "@/components/Home";
import News from "@/components/News";
import Message from "@/components/Message";
import Detail from "@/components/Detail";
const router = new VueRouter({
routes:[
{
path:'/about',
component: About
},
{
path: '/home',
component: Home,
children:[
{
path:'news',
component: News
},
{
path: 'message',
component: Message,
children: [
{
name:'xq',
path: 'detail/:id/:title',// params传参 在路径中先占位
component: Detail,
}
]
}
]
}
]
})
export default router;
import Vue from 'vue'
import App from './App.vue'
import store from "./store";
import VueRouter from "vue-router";
import router from "./router";
Vue.config.productionTip = false
Vue.use(VueRouter)
new Vue({
// render: h => h(App),
// 完整的写法
render(createElement){
return createElement(App)
},
store,
router
}).$mount('#app')
<template>
<div id="app">
<div class="row">
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header">
<h2>Vue 路由案例</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!-- 原始的HTML 实现页面的跳转 -->
<!-- <a class="list-group-item active" href="./about">About</a>-->
<!-- <a class="list-group-item active" href="./home">Home</a>-->
<!-- 在Vue中借助router-link 实现路由的切换 -->
<router-link class="list-group-item active" to="/about">
About
</router-link>
<router-link class="list-group-item active" to="/home">
Home
</router-link>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<!-- 指定组件的展示位置-->
<router-view></router-view>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style>
</style>
路由的props配置
作用
让路由组件更方便的接收到 参数
使用方式有三种
传值:
- props 值为 对象 该对象中所有的key-value的组合最终都会通过props传给Detail组件
- props: {
userName: ‘张三’,
age: 18
}
- props: {
- props值为布尔值_,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件_
- props: true
- props值为函数_,该函数返回的对象中每一组key-value都会通过props传给Detail组件_
- props($route){
return {
id: $route.params.id,
title: $route.params.title
}
}
- props($route){
接收、使用:
- props:[‘id’,‘title’]
-
- 消息编号:{{ id }}
- 消息标题:{{ title }}
案例
<template>
<div>
<h2>我是About组件的内容</h2>
</div>
</template>
<script>
export default {
name: "About"
}
</script>
<style scoped>
</style>
<template>
<div>
<h2>我是Home组件的内容</h2>
<div>
<ul class="nav nav-tabs">
<li>
<router-link class="list-group-item" active-class="active" to="/home/news">
News
</router-link>
</li>
<li>
<router-link class="list-group-item" active-class="active" to="/home/message">
Message
</router-link>
</li>
</ul>
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: "Home"
}
</script>
<style scoped>
</style>
<template>
<ul>
<li>news001<input/></li>
<li>news002<input/></li>
<li>news003<input/></li>
</ul>
</template>
<script>
export default {
name: "News"
}
</script>
<style scoped>
</style>
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<!-- params 传参-->
<router-link :to="{
name: 'xq',
params: {
id: m.id,
title: m.title
}
}">
{{ m.title }}
</router-link>
</li>
<input/>
</ul>
<hr/>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "Message",
data(){
return{
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'}
]
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<ul>
<li>
消息编号:{{ id }}
</li>
<li>
消息标题:{{ title }}
</li>
</ul>
</div>
</template>
<script>
export default {
name: "Detail",
props:['id','title']
}
</script>
<style scoped>
</style>
import VueRouter from "vue-router";
import About from "@/components/About";
import Home from "@/components/Home";
import News from "@/components/News";
import Message from "@/components/Message";
import Detail from "@/components/Detail";
const router = new VueRouter({
routes:[
{
path:'/about',
component: About
},
{
path: '/home',
component: Home,
children:[
{
path:'news',
component: News
},
{
path: 'message',
component: Message,
// props: {
// userName: '张三',
// age: 18
// },
children: [
{
name:'xq',
path: 'detail/:id/:title',// params 传参 /:id/:title 在路径中先占位
component: Detail,
// props: {
// userName: '张三',
// age: 18
// }
props: true
// props($route){
// return {
// id: $route.params.id,
// title: $route.params.title
// }
// }
}
]
}
]
}
]
})
export default router;
import Vue from 'vue'
import App from './App.vue'
import store from "./store";
import VueRouter from "vue-router";
import router from "./router";
Vue.config.productionTip = false
Vue.use(VueRouter)
new Vue({
// render: h => h(App),
// 完整的写法
render(createElement){
return createElement(App)
},
store,
router
}).$mount('#app')
<template>
<div id="app">
<div class="row">
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header">
<h2>Vue 路由案例</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!-- 原始的HTML 实现页面的跳转 -->
<!-- <a class="list-group-item active" href="./about">About</a>-->
<!-- <a class="list-group-item active" href="./home">Home</a>-->
<!-- 在Vue中借助router-link 实现路由的切换 -->
<router-link class="list-group-item active" to="/about">
About
</router-link>
<router-link class="list-group-item active" to="/home">
Home
</router-link>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<!-- 指定组件的展示位置-->
<router-view></router-view>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style>
</style>
router-link的replace属性 和 push属性
- 作用:控制路由跳转时操作浏览器历史记录的模式
- 浏览器的历史记录有两种写入方式:分别为push和replace,push是追加历史记录,replace是替换当前记录。路由跳转时候默认为push
- 如何开启replace模式:
<router-link **replace **:to="{
name: ‘xq’,
params: {
id: m.id,
title: m.title
}
}">
{{ m.title }}
push 本质是向history栈中添加一个路由,在我们看来是切换路由,但本质是在添加一个history记录
案例
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<!-- params 传参-->
<router-link replace :to="{
name: 'xq',
params: {
id: m.id,
title: m.title
}
}">
{{ m.title }}
</router-link>
<button @click="showPush(m)">push查看</button>
<button @click="showReplace(m)">replace查看</button>
</li>
<input/>
</ul>
<hr/>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "Message",
props: ['userName','age'],
data(){
return{
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'}
]
}
},
methods:{
showPush(m){
this.$router.push({
name:'xq',
params: {
id: m.id,
title: m.title
}
})
},
showReplace(m){
this.$router.replace({
name:'xq',
params:{
id: m.id,
title: m.title
}
})
}
}
}
</script>
<style scoped>
</style>
编程式路由导航
作用:不借助 实现路由跳转,让路由跳转更加灵活
- this.$router.back() 浏览器历史记录后退-1
- this.$router.forward() 浏览器历史记录前进1
- this.$router.go(- + x) 正 前进x 负数 后退-x
案例
<template>
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header">
<button @click="back">后退</button>
<button @click="forWard">前进</button>
<button @click="go">后退 * 3</button>
</div>
</div>
</template>
<script>
export default {
name: "Banner",
methods:{
back(){
this.$router.back();
},
forWard(){
this.$router.forward();
},
go(){
this.$router.go(-3);
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<h2>我是About组件的内容</h2>
</div>
</template>
<script>
export default {
name: "About"
}
</script>
<style scoped>
</style>
<template>
<div>
<h2>我是Home组件的内容</h2>
<div>
<ul class="nav nav-tabs">
<li>
<router-link class="list-group-item" active-class="active" to="/home/news">
News
</router-link>
</li>
<li>
<router-link class="list-group-item" active-class="active" to="/home/message">
Message
</router-link>
</li>
</ul>
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: "Home"
}
</script>
<style scoped>
</style>
<template>
<ul>
<li>news001<input/></li>
<li>news002<input/></li>
<li>news003<input/></li>
</ul>
</template>
<script>
export default {
name: "News"
}
</script>
<style scoped>
</style>
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<!-- params 传参-->
<router-link :to="{
name: 'xq',
params: {
id: m.id,
title: m.title
}
}">
{{ m.title }}
</router-link>
</li>
<input/>
</ul>
<hr/>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "Message",
data(){
return{
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'}
]
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<Banner/>
<ul>
<li>
消息编号:{{ id }}
</li>
<li>
消息标题:{{ title }}
</li>
</ul>
</div>
</template>
<script>
import Banner from "@/components/Banner";
export default {
name: "Detail",
components:{Banner},
props:['id','title']
}
</script>
<style scoped>
</style>
import VueRouter from "vue-router";
import About from "@/components/About";
import Home from "@/components/Home";
import News from "@/components/News";
import Message from "@/components/Message";
import Detail from "@/components/Detail";
const router = new VueRouter({
routes:[
{
path:'/about',
component: About
},
{
path: '/home',
component: Home,
children:[
{
path:'news',
component: News
},
{
path: 'message',
component: Message,
// props: {
// userName: '张三',
// age: 18
// },
children: [
{
name:'xq',
path: 'detail/:id/:title',// params 传参 /:id/:title 在路径中先占位
component: Detail,
// props: {
// userName: '张三',
// age: 18
// }
props: true
// props($route){
// return {
// id: $route.params.id,
// title: $route.params.title
// }
// }
}
]
}
]
}
]
})
export default router;
import Vue from 'vue'
import App from './App.vue'
import store from "./store";
import VueRouter from "vue-router";
import router from "./router";
Vue.config.productionTip = false
Vue.use(VueRouter)
new Vue({
// render: h => h(App),
// 完整的写法
render(createElement){
return createElement(App)
},
store,
router
}).$mount('#app')
<template>
<div id="app">
<div class="row">
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header">
<h2>Vue 路由案例</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!-- 原始的HTML 实现页面的跳转 -->
<!-- <a class="list-group-item active" href="./about">About</a>-->
<!-- <a class="list-group-item active" href="./home">Home</a>-->
<!-- 在Vue中借助router-link 实现路由的切换 -->
<router-link class="list-group-item active" to="/about">
About
</router-link>
<router-link class="list-group-item active" to="/home">
Home
</router-link>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<!-- 指定组件的展示位置-->
<router-view></router-view>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style>
</style>
缓存路由组件
- 作用:让不展示的路由组件保持挂载,不被销毁。
- include 中写 想要缓存 的组件名称 不写 表示 缓存所有,写了则表示这组件开启了缓存
- include=“组件名” 表示这个组件启用了 缓存组件
- include="[‘组件名1’,‘组件名2’,…]" 表示多个组件启用了 缓存组件
缓存组件
<!-- 缓存组件 -->
<keep-alive include="News">
<router-view></router-view>
</keep-alive>
两个生命周期钩子
当页面被keep-alive缓存下来的时候,vuet提供两个钩子函数
activated
被 keep-alive 缓存的组件激活时调用。
deactivated
被 keep-alive 缓存的组件失活时调用。
注:这两个状态不算在直接的生命周期里,这两个生命周期钩子需要配合前面的缓存路由组件使用(没有缓存路由组件不起效果)
当keep-alive页面缓存,有activated钩子和created钩子函数时
这两个函数会被同时触发,此时应该使用activated代替created,因为created只会触发一次
页面被缓存下来的时候,就不会触发destroyed生命钩子
取而代之触发的是deactivated钩子
然后引出我们keep-alive里边的两个属性
include 字符串或正则表达,只有匹配的组件会被缓存
exclude 字符串或正则表达式 ,任何匹配的组件都不会被缓存
路由守卫
- 作用:对路由进行权限控制
- 分类:全局守卫、独享守卫、组件内守卫
- 全局路由守卫
- 由于在任何组件中都能使用this.$router,所以全局路由守卫可以在任意组件中调用(可以放在任意组件中,放main.js中也可以)
- beforeEach() 前置路由守卫
// 如果想限制所有路由的跳转,可以使用router对象调用全局路由守卫
router.beforeEach(function(to, from, next){
// 任何一个路由跳转都会经过这个路由守卫
console.log("全局路由进入之前", to.fullPath, from.fullPath);
next()
})
2. afterEach() 后置路由守卫
// 路由跳转之后的守卫,next不调用也无所谓
router.afterEach(function(to, from, next){
// 任何一个路由跳转都会经过这个路由守卫
console.log("全局路由进入之后", to.fullPath, from.fullPath);
})
- 独享守卫
- beforeEnter()
{
path: '/',
name: 'Home',
component: Home,
// 路由配置对象中可添加路由守卫函数,只监听单个路由
beforeEach: (to, from, next) => {
console.log("单个路由守卫进入之前", to.fullPath, from.fullPath);
next()
}
}
- 组件内的路由守卫
- beforeRouteEnter()
// 路由守卫:判断路由能否跳转,可控制路由跳转(多做登录认证)
beforeRouteEnter (to, from, next) {
/* 路由守卫有三个参数,
to表示即将跳转的路由信息对象(到哪去,跳到当前页的路由对象),
from是路由跳转的来源信息对象(从哪来,从哪里调到此页面的路由对象),
next函数,调用时允许路由进入 */
console.log("路由进入之前", to, from, next);
/* 此时,to的路径必定是/about,如果from的路由路径也是about,会报错,
此时需要禁止路由跳转,防止报错
next(); // 是否允许被跳转
使用场景:这个路由守卫,常用于做登录认证,在这里判断用户是否已经登录,
如果已经登录,调用next()允许进入,如果没有登录,不调用next(),禁止进入。
主要针对些需要登录状态才能访问的页面,如:个人信息页 */
console.log(this);
// 路由进入之前,组件还未创建,打印this是undefined,this是不能调的,
// 那么如何在这个路由守卫中获取组件对象this?
next((vm)=>{
// next()的参数是一个回调函数,当组件创建完成后调用,回调的函数就是组件对象this
console.log(vm);
})
},
2. beforeRouterUpdate()
// 路由守卫:当路由路径来源和目标相同时(当前页跳转当前页),
// 参数不同时,执行这个路由守卫,不会报错(如果参数相同,会直接报错,不会进入路由守卫)
beforeRouteUpdate (to, from, next){
console.log("路由更新之前", to, from, this.$route);
// 此时这里的this.$route和from里的page一直是不变的是旧的信息,
// to对象里的数据才是最新值,所以用to.query.page拿到最新的数据
this.$axios.get("/douyu/api/room/list", {
params: { page: to.query.page }
}).then(res => {
console.log(res.data.data.list);
this.list = res.data.data.list
})
next();
// 使用场景:这个路由守卫,常用于写搜索页,当搜索关键词更新时,
// 组件并没有重置也没有显示隐藏,所以普通的生命周期钩子并不会触发,只能在这里更新数据
},
3. beforeRouteLeave()
// 路由守卫:路由离开前,从当前页跳转到其它页之前调用
beforeRouteLeave (to, from, next) {
console.log("路由离开之前", to.path, from.path, next);
next()
// 使用场景,比如我们网站中遇到的关不掉的广告页面
// 比如我们在这个函数中能够不掉用next函数,当前页面就不能跳转到其它页面了
}
- 路由守卫的参数有三个: to, from , next
- to: 表示即将跳转的路由信息对象(到哪去,跳到当前页的路由对象)
- from: 是路由跳转的来源信息对象(从哪来,从哪里调到此页面的路由对象)
- next: 回调函数, 表示是否允许路由跳转, 调用允许, 不调用则禁止(表示是否放行)
全局守卫
import VueRouter from "vue-router";
import About from "@/components/About";
import Home from "@/components/Home";
import News from "@/components/News";
import Message from "@/components/Message";
import Detail from "@/components/Detail";
const router = new VueRouter({
routes:[
{
path:'/about',
component: About
},
{
path: '/home',
component: Home,
children:[
{
path:'news',
component: News,
},
{
path: 'message',
component: Message,
children: [
{
name:'xq',
path: 'detail/:id/:title',// params 传参 /:id/:title 在路径中先占位
component: Detail,
props: true
}
]
}
]
}
]
})
// 全局 路由首位
router.beforeEach((to,from,next)=>{
console.log("前置路由守卫",to,from,next);
next(); // 放行
});
router.afterEach((to, from,)=>{
console.log("后置路由守卫",to,from)
})
export default router;
独享守卫
import VueRouter from "vue-router";
import About from "@/components/About";
import Home from "@/components/Home";
import News from "@/components/News";
import Message from "@/components/Message";
import Detail from "@/components/Detail";
const router = new VueRouter({
routes:[
{
path:'/about',
component: About
},
{
path: '/home',
component: Home,
children:[
{
path:'news',
component: News,
// 独享守卫
beforeEnter(to,from,next){
console.log("独享路由守卫");
next();
}
},
{
path: 'message',
component: Message,
children: [
{
name:'xq',
path: 'detail/:id/:title',// params 传参 /:id/:title 在路径中先占位
component: Detail,
props: true
}
]
}
]
}
]
})
export default router;
组件内守卫
<template>
<div>
<h2>我是About组件的内容</h2>
</div>
</template>
<script>
export default {
name: "About",
beforeRouteEnter(to,from,next){
console.log("组件内路由守卫 beforeRouterEnter");
next();
},
beforeRouteLeave(to,from,next){
console.log("组件内路由守卫 beforeRouterLeave");
next()
}
}
</script>
<style scoped>
</style>
最后页面效果