Vue基础25之路由第四节

路由

编程式路由导航

Home.vue(去掉两个router-line的replace)

<template>
  <div>
    <h1>我是Home的内容</h1>
    <br>
    <div class="btn-group" role="group" aria-label="...">
      <router-link  type="button" class="btn btn-default"  active-class="active" to="/home/news">News</router-link>
      <router-link  type="button" class="btn btn-default"  active-class="active" to="/home/message">Message</router-link>
    </div>
    <br><br>
    <router-view></router-view>
  </div>
</template>

<script>
    export default {
        name: "Home",
        /*mounted(){
          console.log("Home组件被挂载了")
          window.homeRoute=this.$route
          window.homeRouter=this.$router
        },
        beforeDestroy() {
          console.log("Home组件被销毁了")
        }*/
    }
</script>

<style scoped lang="less">
</style>

HomeMessage.vue

<template>
  <div>
    <button @click="goTest(2)">go查看测试(前进2步)</button>
    <ul>
<!--      跳转路由并携带params参数,to的字符串的写法-->
      <li v-for="m in messageList" :key="m.id">
<!--        <router-link  :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link>-->

        <!--      跳转路由并携带params参数,只能使用名字跳转,to的对象的写法-->
        <router-link  :to="{
          name:'xiangqing',
          query:{
            id:m.id,
            title:m.title
          }
        }">
          {{m.title}}
        </router-link>
        <button @click="pushShow(m)">push查看</button>
        <button @click="replaceShow(m)">replace查看</button>
        <button @click="goTest(-3)">go查看测试(后退3步)</button>

        <br>
      </li>
    </ul>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
    export default {
        name: "HomeMessage",
      data(){
          return{
            messageList:[
              {id:"001",title:"消息001"},
              {id:"002",title:"消息002"},
              {id:"003",title:"消息003"},
            ]
          }
      },
      methods:{
        pushShow(m){
          console.log(this.$router)
          this.$router.push({
            name:'xiangqing',
            query:{
              id:m.id,
              title:m.title
            }
          })
        },
        replaceShow(m){
          this.$router.replace({
            name:'xiangqing',
            query:{
              id:m.id,
              title:m.title
            }
          })
        },
        goTest(value){
          this.$router.go(value)
        }
      }
    }
</script>

<style scoped>
.active{
  color: black;
}
</style>

Banner.vue

<template>
<div>
  <h1>Vue Router Demo</h1>
  <button @click="back()">后退</button>
  <button @click="forward()">前进</button>
  <br>
  <br>
</div>
</template>

<script>
    export default {
        name: "Banner",
      methods:{
        back(){
          this.$router.back()
        },
        forward(){
          this.$router.forward()
        }
      }
    }
</script>

<style scoped>
h1{
  border-bottom: 1px solid #ccc;
}
</style>

请添加图片描述

总结

  1. 作用:不借助<router-link>实现路由跳转,让路由跳转更加灵活
  2. 具体编码:
//$router的两个API
this.$router.push({
   name:'xiangqing',
   query:{
     id:m.id,
     title:m.title
   }
 })


 this.$router.replace({
   name:'xiangqing',
   query:{
     id:m.id,
     title:m.title
   }
 })

this.$router.back()  //后退
this.$router.forward() //前进
this.$router.go(3)  //可前进也可后退
  1. 补充一个$router的api:go
    go函数的参数表示浏览器历史记录前进/后退几步(正数为前进,负数为后退)

缓存路由组件

Home.vue

<template>
  <div>
    <h1>我是Home的内容</h1>
    <br>
    <div class="btn-group" role="group" aria-label="...">
      <router-link  type="button" class="btn btn-default"  active-class="active" to="/home/news">News</router-link>
      <router-link  type="button" class="btn btn-default"  active-class="active" to="/home/message">Message</router-link>
    </div>
    <br><br>
<!--    include后面跟的是组件名-->
    <keep-alive include="HomeNews">
      <router-view></router-view>
    </keep-alive>
  </div>
</template>

<script>
    export default {
        name: "Home",
        /*mounted(){
          console.log("Home组件被挂载了")
          window.homeRoute=this.$route
          window.homeRouter=this.$router
        },
        beforeDestroy() {
          console.log("Home组件被销毁了")
        }*/
    }
</script>

<style scoped lang="less">
</style>

HomeNews.vue

<template>
<div>
  <ul>
    <li>新闻001 <input type="text"></li>
    <li>新闻002 <input type="text"></li>
    <li>新闻003 <input type="text"></li>
  </ul>
</div>
</template>

<script>
    export default {
        name: "HomeNews",
      beforeDestroy() {
        console.log("HomeNews组件即将被销毁")
      }
    }
</script>

<style scoped>

</style>

HomeMessage.vue

<template>
  <div>
    <ul>
<!--      跳转路由并携带params参数,to的字符串的写法-->
      <li v-for="m in messageList" :key="m.id">
<!--        <router-link  :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link>-->

        <!--      跳转路由并携带params参数,只能使用名字跳转,to的对象的写法-->
        <router-link  :to="{
          name:'xiangqing',
          query:{
            id:m.id,
            title:m.title
          }
        }">
          {{m.title}}
        </router-link>
        <button @click="pushShow(m)">push查看</button>
        <button @click="replaceShow(m)">replace查看</button>

        <br>
      </li>
    </ul>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
    export default {
        name: "HomeMessage",
      data(){
          return{
            messageList:[
              {id:"001",title:"消息001"},
              {id:"002",title:"消息002"},
              {id:"003",title:"消息003"},
            ]
          }
      },
      methods:{
        pushShow(m){
          console.log(this.$router)
          this.$router.push({
            name:'xiangqing',
            query:{
              id:m.id,
              title:m.title
            }
          })
        },
        replaceShow(m){
          this.$router.replace({
            name:'xiangqing',
            query:{
              id:m.id,
              title:m.title
            }
          })
        },

      },
      beforeDestroy() {
        console.log("HomeMessage组件即将被销毁")
      }
    }
</script>

<style scoped>
.active{
  color: black;
}
</style>

请添加图片描述

总结

  1. 作用:让不展示的路由组件保持挂载,不被销毁
  2. 具体编码:
<keep-alive include="HomeNews">
     <router-view></router-view>
</keep-alive>

两个新的生命周期钩子

保留缓存组件功能后新增的需求

HomeNews.vue

<template>
<div>
  <div :style="{opacity}">欢迎学习Vue</div>
  <ul>
    <li>新闻001 <input type="text"></li>
    <li>新闻002 <input type="text"></li>
    <li>新闻003 <input type="text"></li>
  </ul>
</div>
</template>

<script>
    export default {
        name: "HomeNews",
      data(){
          return{
            opacity: 1
          }
      },
      activated() {
        console.log("News组件被激活了")
        this.timer=setInterval(()=>{
          console.log("@")
         this.opacity-=0.01
          if(this.opacity<0) this.opacity=1

        },16)
      },
      deactivated() {
        console.log("News组件失活了")
        clearInterval(this.timer)
      }
    }
</script>

<style scoped>

</style>

HomeMessage.vue

<template>
  <div>
    <ul>
<!--      跳转路由并携带params参数,to的字符串的写法-->
      <li v-for="m in messageList" :key="m.id">
<!--        <router-link  :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link>-->

        <!--      跳转路由并携带params参数,只能使用名字跳转,to的对象的写法-->
        <router-link  :to="{
          name:'xiangqing',
          query:{
            id:m.id,
            title:m.title
          }
        }">
          {{m.title}}
        </router-link>
        <button @click="pushShow(m)">push查看</button>
        <button @click="replaceShow(m)">replace查看</button>

        <br>
      </li>
    </ul>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
    export default {
        name: "HomeMessage",
      data(){
          return{
            messageList:[
              {id:"001",title:"消息001"},
              {id:"002",title:"消息002"},
              {id:"003",title:"消息003"},
            ]
          }
      },
      methods:{
        pushShow(m){
          console.log(this.$router)
          this.$router.push({
            name:'xiangqing',
            query:{
              id:m.id,
              title:m.title
            }
          })
        },
        replaceShow(m){
          this.$router.replace({
            name:'xiangqing',
            query:{
              id:m.id,
              title:m.title
            }
          })
        },

      },
    }
</script>

<style scoped>
.active{
  color: black;
}
</style>

Home.vue

<template>
  <div>
    <h1>我是Home的内容</h1>
    <br>
    <div class="btn-group" role="group" aria-label="...">
      <router-link  type="button" class="btn btn-default"  active-class="active" to="/home/news">News</router-link>
      <router-link  type="button" class="btn btn-default"  active-class="active" to="/home/message">Message</router-link>
    </div>
    <br><br>
<!--    include后面跟的是组件名-->
    <keep-alive include="HomeNews">
      <router-view></router-view>
    </keep-alive>
  </div>
</template>

<script>
    export default {
        name: "Home",
        /*mounted(){
          console.log("Home组件被挂载了")
          window.homeRoute=this.$route
          window.homeRouter=this.$router
        },
        beforeDestroy() {
          console.log("Home组件被销毁了")
        }*/
    }
</script>

<style scoped lang="less">
</style>

请添加图片描述

总结

  1. 作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。
  2. 具体名字
    (1)activated路由组件被激活时触发
    (2)deactivated路由组件失活时触发

全局路由守卫

路由前置守卫

src/router/index.js
//该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
//引入组件
import About from "@/pages/About";
import Home from "@/pages/Home";
import HomeNews from "@/pages/HomeNews";
import HomeMessage from "@/pages/HomeMessage";
import Detail from "@/pages/Detail";

//创建并暴露一个路由器
const router=new VueRouter({
    routes:[
        {
            name:'guanyu',
            path:'/about',
            component:About
        },
        {
            name:"zhuye",
            path:'/home',
            component:Home,
            children:[
                {
                    name:'xinwen',
                    path:'news',
                    component:HomeNews
                },
                {
                    name:'xiaoxi',
                    path:'message',
                    component:HomeMessage,
                    children:[
                        {
                            name:'xiangqing',
                            // path:'detail/:id/:title',  //nodejs的占位符,后面会填充内容
                            path:'detail',  //query的写法
                            component:Detail,
                            //props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件
                            // props:{a:1,b:'你好啊'},

                            //props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件
                            // props:true,

                            //props的第三种写法:函数式(最普通的写法)
                            /*props($route){
                                return {id:$route.query.id,title:$route.query.title}
                            }*/

                            //第三种:函数式(解构赋值的写法)
                            /*props({query}){
                                return{id:query.id,title:query.title}
                            }*/

                            //第三种:函数式(解构赋值之后再解构赋值)
                            props({query:{id,title}}){
                                return {id,title}
                            }
                        }
                    ]
                }
            ]
        }
    ]
})

//全局前置路由守卫——初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,from,next)=>{
    console.log("to",to)
    console.log("from",from)
    if(to.name=="xinwen"||to.path=="/home/message"){
        console.log(localStorage.getItem("school"))
        if(localStorage.getItem("school")==="lucky"){
            next()
        }else{
            alert("学校名字不对,无权限查看")
        }
    }else{
        next()
    }
})

export default  router

请添加图片描述

路由后置守卫及用户鉴权问题

src/router/index.js
//该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
//引入组件
import About from "@/pages/About";
import Home from "@/pages/Home";
import HomeNews from "@/pages/HomeNews";
import HomeMessage from "@/pages/HomeMessage";
import Detail from "@/pages/Detail";

//创建并暴露一个路由器
const router=new VueRouter({
    routes:[
        {
            name:'guanyu',
            path:'/about',
            component:About,
            meta:{title:"关于"}
        },
        {
            name:"zhuye",
            path:'/home',
            component:Home,
            meta:{title:"主页"},
            children:[
                {
                    name:'xinwen',
                    path:'news',
                    component:HomeNews,
                    meta:{isAuth:true,title:"新闻"},  //增加权限控制
                },
                {
                    name:'xiaoxi',
                    path:'message',
                    component:HomeMessage,
                    meta:{isAuth: true,title:"消息"},
                    children:[
                        {
                            name:'xiangqing',
                            // path:'detail/:id/:title',  //nodejs的占位符,后面会填充内容
                            path:'detail',  //query的写法
                            component:Detail,
                            meta:{isAuth: true,title:"详情"},
                            //props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件
                            // props:{a:1,b:'你好啊'},

                            //props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件
                            // props:true,

                            //props的第三种写法:函数式(最普通的写法)
                            /*props($route){
                                return {id:$route.query.id,title:$route.query.title}
                            }*/

                            //第三种:函数式(解构赋值的写法)
                            /*props({query}){
                                return{id:query.id,title:query.title}
                            }*/

                            //第三种:函数式(解构赋值之后再解构赋值)
                            props({query:{id,title}}){
                                return {id,title}
                            }
                        }
                    ]
                }
            ]
        }
    ]
})

//全局前置路由守卫——初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,from,next)=>{
    console.log("前置守卫",to,from)
    // if(to.name=="xinwen"||to.path=="/home/message"){
    if(to.meta.isAuth){  //判断是否需要鉴权
        if(localStorage.getItem("school")==="lucky"){
            next()
        }else{
            alert("学校名字不对,无权限查看")
        }
    }else{
        next()
    }
})

//全局后置路由守卫——初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{
    console.log("后置路由守卫",to,from)
    document.title=to.meta.title||"xx系统"
})
export default  router

请添加图片描述

总结

  1. 作用:对路由进行权限控制
  2. 分类:全局守卫、独享守卫、组件内守卫
  3. 全局守卫
//全局前置路由守卫——初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,from,next)=>{
    console.log("前置守卫",to,from)
    if(to.meta.isAuth){  //判断是否需要鉴权(判断当前路由是否需要进行权限控制)
        if(localStorage.getItem("school")==="lucky"){//权限控制的具体规则
            next()  //放行
        }else{
            alert("学校名字不对,无权限查看") //暂无权限
        }
    }else{
        next()  //放行
    }
})

//全局后置路由守卫——初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{
    console.log("后置路由守卫",to,from)
    if(to.meta.title){
		document.title=to.meta.title||"xx系统"  //修改网页的title
	}else{
		document.title="vue_test"  //修改网页的title
	}
})
export default  router

独享路由守卫

src/router/index.js

//该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
//引入组件
import About from "@/pages/About";
import Home from "@/pages/Home";
import HomeNews from "@/pages/HomeNews";
import HomeMessage from "@/pages/HomeMessage";
import Detail from "@/pages/Detail";

//创建并暴露一个路由器
const router=new VueRouter({
    routes:[
        {
            name:'guanyu',
            path:'/about',
            component:About,
            meta:{title:"关于"}
        },
        {
            name:"zhuye",
            path:'/home',
            component:Home,
            meta:{title:"主页"},
            children:[
                {
                    name:'xinwen',
                    path:'news',
                    component:HomeNews,
                    meta:{isAuth:true,title:"新闻"},  //增加权限控制
                    //独享前置路由守卫(只有前置)
                    beforeEnter:(to, from, next)=>{
                        if(to.meta.isAuth){  //判断是否需要鉴权
                            if(localStorage.getItem('school')==='lucky'){
                                next()
                            }else{
                                alert("学校名不对,无权限查看!")
                            }
                        }else{
                            next()
                        }
                    }
                },
                {
                    name:'xiaoxi',
                    path:'message',
                    component:HomeMessage,
                    meta:{isAuth: true,title:"消息"},
                    children:[
                        {
                            name:'xiangqing',
                            // path:'detail/:id/:title',  //nodejs的占位符,后面会填充内容
                            path:'detail',  //query的写法
                            component:Detail,
                            meta:{isAuth: true,title:"详情"},
                            //props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件
                            // props:{a:1,b:'你好啊'},

                            //props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件
                            // props:true,

                            //props的第三种写法:函数式(最普通的写法)
                            /*props($route){
                                return {id:$route.query.id,title:$route.query.title}
                            }*/

                            //第三种:函数式(解构赋值的写法)
                            /*props({query}){
                                return{id:query.id,title:query.title}
                            }*/

                            //第三种:函数式(解构赋值之后再解构赋值)
                            props({query:{id,title}}){
                                return {id,title}
                            }
                        }
                    ]
                }
            ]
        }
    ]
})

//全局后置路由守卫——初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{
    console.log("后置路由守卫",to,from)
    document.title=to.meta.title||"xx系统"
})
export default  router

请添加图片描述

总结

  1. 独享守卫
//独享前置路由守卫(只有前置)
 beforeEnter(to, from, next){
     if(to.meta.isAuth){  //判断当前路由是否需要权限控制
         if(localStorage.getItem('school')==='lucky'){
             next()
         }else{
             alert("学校名不对,无权限查看!")
         }
     }else{
         next()
     }
 }

组件内路由守卫

在这里插入图片描述

src/router/index.js(改了about的用户鉴权)

//该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
//引入组件
import About from "@/pages/About";
import Home from "@/pages/Home";
import HomeNews from "@/pages/HomeNews";
import HomeMessage from "@/pages/HomeMessage";
import Detail from "@/pages/Detail";

//创建并暴露一个路由器
const router=new VueRouter({
    routes:[
        {
            name:'guanyu',
            path:'/about',
            component:About,
            meta:{isAuth:true,title:"关于"},//设置权限
        },
        {
            name:"zhuye",
            path:'/home',
            component:Home,
            meta:{title:"主页"},
            children:[
                {
                    name:'xinwen',
                    path:'news',
                    component:HomeNews,
                    meta:{isAuth:true,title:"新闻"},  //增加权限控制
                    //独享前置路由守卫(只有前置)
                    beforeEnter:(to, from, next)=>{
                        if(to.meta.isAuth){  //判断是否需要鉴权
                            if(localStorage.getItem('school')==='lucky'){
                                next()
                            }else{
                                alert("学校名不对,无权限查看!")
                            }
                        }else{
                            next()
                        }
                    }
                },
                {
                    name:'xiaoxi',
                    path:'message',
                    component:HomeMessage,
                    meta:{isAuth: true,title:"消息"},
                    children:[
                        {
                            name:'xiangqing',
                            // path:'detail/:id/:title',  //nodejs的占位符,后面会填充内容
                            path:'detail',  //query的写法
                            component:Detail,
                            meta:{isAuth: true,title:"详情"},
                            //props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件
                            // props:{a:1,b:'你好啊'},

                            //props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件
                            // props:true,

                            //props的第三种写法:函数式(最普通的写法)
                            /*props($route){
                                return {id:$route.query.id,title:$route.query.title}
                            }*/

                            //第三种:函数式(解构赋值的写法)
                            /*props({query}){
                                return{id:query.id,title:query.title}
                            }*/

                            //第三种:函数式(解构赋值之后再解构赋值)
                            props({query:{id,title}}){
                                return {id,title}
                            }
                        }
                    ]
                }
            ]
        }
    ]
})

//全局前置路由守卫——初始化的时候被调用、每次路由切换之前被调用
/*router.beforeEach((to,from,next)=>{
    console.log("前置守卫",to,from)
    // if(to.name=="xinwen"||to.path=="/home/message"){
    if(to.meta.isAuth){  //判断是否需要鉴权
        if(localStorage.getItem("school")==="lucky"){
            next()
        }else{
            alert("学校名字不对,无权限查看")
        }
    }else{
        next()
    }
})*/

//全局后置路由守卫——初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{
    // console.log("后置路由守卫",to,from)
    document.title=to.meta.title||"xx系统"
})
export default  router

About.vue

<template>
    <h1>我是About的内容</h1>
</template>

<script>
export default {
  name: "About",
  /*mounted(){
    console.log("About组件被挂载了",this)
    window.aboutRoute=this.$route
    window.aboutRouter=this.$router
  },
  beforeDestroy() {
    console.log("About组件被销毁了")
  }*/
  //通过路由规则,进入该组件时被调用
  beforeRouteEnter(to,from,next){
    console.log("About-beforeRouteEnter",to,from)
    if(to.meta.isAuth){
      if(localStorage.getItem("school")=="lucky"){
        next()
      }else{
        alert("学校名不对,无权限查看")
      }
    }else{
      next()
    }
  },
  //通过路由规则,离开该组件时被调用
  beforeRouteLeave(to,from,next){
    console.log("About--beforeRouteLeave",to,from)
    next()
  }
}
</script>

<style scoped>

</style>

请添加图片描述

总结

组件内守卫:

//进入守卫,通过路由规则,进入该组件时被调用
beforeRouteEnter(to,from,next){
  },
//离开守卫,通过路由规则,离开该组件时被调用
beforeRouteLeave(to,from,next){
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值