❤ 在安装完依赖之后
全局路由守卫:
- beforeEach –
- beforeResolve –
- afterEach –
局部路由守卫
- beforeDestroy – 销毁前
- beforeRouteEnter – 路由进入前(不可使用this,但可以使用vm)
- beforeRouteUpdate – url更新前(本页面跳转本页面( EG:跳转不同商品,路由不变,改变id时), 要将生命周期函数内的数据控制,写到此 路由钩子内,因为生命周期此时不会再执行一次,一切生命周期内的方法不会再次执行)
- beforeRouteLeave – 路由离开(监听到用户含有未提交的表单时候,可以在这里做个弹窗,提示用户是否要离开,具体的数据可以使用next(()=>{ // if(this.username){ //do somthing}})) ,以提高用户体验
router - index.js路由守卫是出现在 生命周期函数之前的
全局守卫 写在index.js中 ; 局部守卫 写在具体的component 中
❤ 全局守卫(router 下 的 index.js)
import Vue from 'vue'
import VueRouter from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import ElementDate from '@/components/elementDate'
import notFound from '@/components/notFound'
Vue.use(VueRouter)
const routes = [
{
path:'/',
component:()=>import('@/components/HelloWorld'),
meta:{title:"HelloWorld Title"}
},
{
// path:'/a/:id',
path:'/a',
props:true,
// component:()=>import('XXXX') 的 好处是 减少首屏所需要花费的时间,提升速度 (类似按需加载)
component:()=>import('@/components/HelloWorld'),
name:"AAAAA",
meta:{title:"HelloWorld Title"}
},
{
// path:'/b/:id', 斜杠后的值会被传给组件,在跳转的时候也要写为 to="/b/123"
path:'/b',
// props:true, // 表示冒号后面的 变量会被以 props 的形式,直接传递给页面 components 页直接 使用props 接受即可
name:"i'm b",
// component:{
// default:ElementDate,
// conA:HelloWorld
// },
component: ElementDate ,
meta:{
title:"ElementDate Title",
description:"my description"
},
children:[{
path:'/childrenPath',
component:HelloWorld
}]
}
// ,{
// path:'/*',
// component:notFound,
// meta:{title:"notFound Title"}
// }
]
const router = new VueRouter({
routes,
mode:'history', // 具体使用的模式
base:'/hubinbing/', // 为url 添加protocal
fallback:true // 若不支持history 则回到hash模式
})
console.log('router ',router)
// 路由全局守卫
router.beforeEach((to,from,next)=>{
console.log('全局路由守卫--beforeEach',to,from)
// 使用 routes 的 item中的 数据 统一改变 切换components 的每个 title
if(to.meta.title)
document.title = to.meta.title
else
document.title = "ch6-2"
next()
})
router.beforeResolve((to,from,next)=>{
console.log('全局路由守卫--beforeResolve',to,from)
next()
})
router.afterEach((to,from)=>{
// let bodySrcollTop = document.body.scrollTop
// console.log("bodySrcollTop ===>",bodySrcollTop)
console.log('全局路由守卫--afterEach',to,from)
// if (bodySrcollTop !== 0) {
// document.body.scrollTop = '210px'
// return
// }
// let docSrcollTop = document.documentElement.scrollTop
// if (docSrcollTop !== 0) {
// document.documentElement.scrollTop = 0
// }
})
export default router;
❤ 局部守卫
export default {
name: 'HelloWorld',
props: {
msg: String
},
beforeCreate () {
console.log("beforeCreate")
},
created () {
console.log("created")
},
beforeMount () {
console.log("beforeMount")
},
mounted () {
console.log("mounted")
},
beforeRouteEnter (to, from, next) {
// 接着 全局守卫 - beforeEach 执行
console.log('局部路由守卫--beforeRouteEnter --- 无法使用this,但可以用vm', to, from)
next()
},
beforeRouteUpdate (to, from, next) {
// 当 url 的path的params发生变化的时候执行此方法(参数更新value=2 --> value = 1)
console.log('局部路由守卫--beforeRouteUpdate -- 可以用this', to, from)
next()
},
beforeRouteLeave (to, from, next) {
//当 url 的 path 变更的时候(页面跳转)
console.log('局部路由守卫--beforeRouteLeave 可以用this', to, from)
next()
}
}
beforeDestroy 是在切换到下个页面的时候 , 上个页面的beforeDestroy 方法开始执行
- 1.所有的前置守卫和beforeRouteEnter无法使用 “this”,因为在生命周期开始之前他们就调用了,此时的this并没有被挂载到具体的dom上
//如果要使用this 可以在守卫中写上
// router-index.js -----
{
path:'/a/:id', // :id 为传递给组件的query
props:true,
component:HelloWorld,
name:"AAAAA",
meta:{title:"HelloWorld Title"}
},
// -----
// url: http://localhost:8080/hubinbing/a/678
data(){return{numBers:159}},
beforeRouteEnter (to, from, next) {
console.log('局部路由守卫--beforeRouteEnter', to, from)
next(vm => console.log("query 传递的值是 : ", vm.id, "本页面data的值 numBers :", vm.numBers))
},
- 2.如果需要在此时使用store中的数据, 可以在index.js 中引入 store ,
import store from ‘@/store’
router.beforeEach((to, form, next) => {
console.log(store.getters)
})
addRoute 用于向route中添加 路由项
- 有一个问题:在最初的时候,我们会配置一个404的not found 路由,而addRoute而来的路由,是继续push的所以在not found 后面,因此会先被not found 匹配掉. 这种情况 该如何解决?
<div @click="addRoute"> addRoute </div>
import comC from '@/components/componetC'
export default {
name: 'HelloWorld',
props: {
msg: String
},
methods: {
addRoute () {
this.$router.addRoutes([
{
path: '/c', component: comC, meta: { title: "ComponenetC Title" }
}])
}
},
总体 demo 代码
app.js 代码
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.config.productionTip = false
Vue.use(ElementUI);
new Vue({
render: h => h(App),
router
}).$mount('#app')
app.vue 代码
<template>
<div id="app">
<transition name="fade">
<router-view></router-view>
<!-- <router-view name="conA"> 只是一种小技巧 ,但是没实现 </router-view> -->
</transition>
<router-link to="/a">helloWorld</router-link>
<router-link to="/b">element</router-link>
</div>
</template>
<script>
export default {
name: 'App',
data () {
return {
}
},
components: {
}
}
</script>
<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>
HelloWorld.vue 代码
<template>
<div class="containerCLs">
<h1>{{ msg }}</h1>
HelloWorld
<button @click="addRoute"> add routes</button>
<br>
<router-link to="/b">to B</router-link>
<!-- <router-link :to="{path:'/b'}">to B</router-link> -->
</div>
</template>
<script>
import comC from '@/components/componetC'
export default {
name: 'HelloWorld',
props: {
msg: String,
id: {
default: "i'm default"
}
},
data () {
return {
numBers: 159
}
},
methods: {
addRoute () {
console.log(this.$router);
this.$router.addRoutes([
{
path: '/c', component: comC, meta: { title: "ComponenetC Title" }
}])
}
},
beforeCreate () {
console.log("beforeCreate")
},
created () {
console.log("created")
},
beforeMount () {
console.log("beforeMount")
},
mounted () {
console.log("mounted")
},
beforeDestroy (to, from) {
console.log('局部路由守卫--beforeDestroy in A', to, from)
},
beforeRouteEnter (to, from, next) {
console.log('局部路由守卫--beforeRouteEnter', to, from)
next(vm => console.log("query 传递的值是 : ", vm.id, "本页面data的值 numBers :", vm.numBers))
},
beforeRouteUpdate (to, from, next) {
console.log('局部路由守卫--beforeRouteUpdate', to, from)
// 重点::! 当我们使用同一个路由 ,只是改变了后面的query,那么页面是不会重新走生命周期的
// 这也意味着,一切在mounted 等生命周期钩子内的函数, 都不会再次执行,页面内的数据也不会再次刷新
// 此情况应该将 周期钩子内的动作 ,放置到局部路由导航中去执行!!
next()
},
beforeRouteLeave (to, from, next) {
console.log('局部路由守卫--beforeRouteLeave', to, from)
console.log('为系统拥有更好的体验,在beforeLeave 钩子这,监听到用户有修改过的表单数据时,弹出弹窗,来让用户确认是否离开 使用v-m', to, from)
// alert("离开?")
next(()=>{if(this.userName){// dosonmething}})
// next()
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.containerCLs {
width: 10000px;
}
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
elementDate.vue 代码
<template>
<div class="containerCLs">
<!-- <br> <br> <br> <br> <br>
<br> <br> <br> <br> <br>
<br> <br> <br> <br> <br>
<br> <br> <br> <br> <br>
<br> <br> <br> <br> <br>
<br> <br> <br> <br> -->
<button>
使用path 跳转
<router-link :to="{path:'/a'}">:to="{path:'/a'}"</router-link>
</button>
<br>
<hr>
<div>使用name 跳转 此处的name 和 path一点关系也没有 ,可以重名 ,但最好不要,以免混淆</div>
<router-link :to="{name:'AAAAA'}">:to="{name:'AAAAA'}"</router-link>
<hr>
<br>
直接跳转(是否算path?)
<router-link to="/a">to="/a"</router-link>
<hr>
</div>
</template>
<script>
export default {
name: 'App',
beforeCreate () {
console.log("beforeCreate")
},
created () {
console.log("created")
},
beforeMount () {
console.log("beforeMount")
},
mounted () {
console.log("this.$route")
console.log(this.$route)
console.log(this.$router)
console.log("this.id" + this.id)
},
beforeDestroy (to, from) {
console.log('局部路由守卫--beforeDestroy in B', to, from)
},
beforeRouteEnter (to, from, next) {
console.log('局部路由守卫--beforeRouteEnter', to, from)
next()
},
beforeRouteUpdate (to, from, next) {
console.log('局部路由守卫--beforeRouteUpdate', to, from)
next()
},
beforeRouteLeave (to, from, next) {
console.log('局部路由守卫--beforeRouteLeave', to, from)
next()
},
props: ["id"],
data () {
return {
}
},
components: {
}
}
</script>
<style scoped>
.containerCLs {
width: 100000px;
}
</style>