13. 编程式导航
1. 编程式导航, 帮助我们切换我们的组件.
2. 之前我们用 router-link 来生成导航的, 我们可以 router-link 生成的标签去切换我们的组件,
3. 编程式导航: 借助于 router 的实例方法, 通过编写代码来实现导航的切换.
(我们除了标签去切换, 我们也可以使用方法去切换导航)
提供的方法:
back 回退一步
forward 前进一步
go 指定前进回退步数
push 导航到不同的 url, 向 history 栈添加一个新的记录
replace 导航到不同 url, 替换 history 栈中当前记录
4. 当我们访问一个网站的时候, 我们要切换不同的导航, 实际上它会把这些导航的记录放在这个浏览器的历史记录栈里面,
然后统一去管理,
5. 在 app.vue 中,
- <input type="button" value="后退" @click="backHandle">
- <input type="button" value="前进" @click="forwardHandle">
- <input type="button" value="控制前进后退的步数" @click="goHandle">
- <input type="button" value="控制指定的导航 Push" @click="pushHandle">
methods 中监控一下:
- methods:{
- backHandle(){
- this.$router.back()
- },
- forwardHandle(){
- this.$router.forward()
- },
- goHandle(){
- this.$router.go(-2)
- },
- pushHandle(){
- //this.$router.push("/user") /*push() 写上目标链接, 写成字符串形式,*/
- this.$router.push({path:'/user'}) /* 也可以写成描述目标地址的一个对象 */
- }
- }
push 导航到不同的 url, 向 history 栈添加一个新的记录
push 会比较常用, 可以根据它跳转到不同的链接上边.
14. 全局钩子函数
1. 导航的钩子函数:
导航发生变化的时候, 导航钩子主要用来拦截导航, 让它完成跳转或取消.
也就是说在我们不同的阶段, 那么它会执行不同的函数, 然后对我们的导航是否要进行跳转或者取消做一个判断,
它很类似我们一个组件的生命周期, 在不同阶段他会触发不同的函数, 这个主要用在路由里面,
也就是我们进入路由之前, 我们可以做些判断, 或进入之后我们可以做些事情, 然后当我们组件更新的时候呢,
它可以触发对应的函数, 然后我们就可以做一些事情了.
执行钩子函数位置:
router 全局
单个路由
组件中
钩子函数:
router 实例上: beforeEach/afterEach
单个路由中: beforeEnter
组件内的钩子: beforeRouteEnter/beforeRouteUpdate/beforeRouteLeave
钩子函数接收的参数
to: 要进入的目标路由对象, 到哪里去
from: 正要离开导航的路由对象, 从哪里来
next: 用来决定跳转或取消导航
2. 在 router 文件夹下的 index.js 中, 找到 router 实例, let router = new Router({
在它身上有一个钩子函数, 就是在你进入每个导航的时候执行的这个函数,
- router.beforeEach(()=>{ // 它接受一个回掉函数
- })
- router.beforeEach(()=>{
- console.log("bv")
- })
打开页面, 打开控制台, 刷新一下, 看到它被执行了, 所以说导航钩子就被执行了, 只要你切换不同的导航,
那么这个导航钩子都会被执行,
但是路由对应的组件并没有被渲染出来,
回到页面,
- router.beforeEach(()=>{
- console.log("bv")
- })
当我们进入导航的时候, 我们先执行一下导航钩子函数, 那我们之前说过, 我们是不是可以利用这种导航的钩子
对导航进行跳转或者取消导航, 这时候我想让他进入导航怎么办呢? 我们需要借助于它给我们提供的参数,
也就是说我们执行 beforeEach 以后呢有回掉函数, 回掉函数他会接收三个参数, 之后钩子函数呢都会接收这三个参数,
- router.beforeEach((to,from,next)=>{
- })
to: 目标导航的一个路由信息对象
from: 离开导航的路由信息对象
next: 当我们进入导航的时候, 他会执行 beforEach, 那我们是否让它进入导航, 取决于第三个参数是否被执行了一下,
- router.beforeEach((to,from,next)=>{
- next() // 路由对应的组件并没有被渲染出来,
- })
3.next() 可以接收一个参数,
next(false) 取消导航, 不让组件进入到对应导航里面来,
4. 除了这种形式, 你还可以给他重定向一个页面中去, 比如说有些页面他需要登陆你才能访问, 这时候呢,
我们在之前就可以判断, 如果你没登陆的话, 我们就可以把你重定向到一个登陆页面上去,
5. 假如你访问 document 页面需要登陆, 在 meta 中写上一个只有我们登陆之后才能到导航里面的组件, 我们需要在 meta 里面写上一个标识,
- {
- path:'/document',
- name:'document',
- //component:document // 一个路由对应一个组件
- components:{ // 一个路由对应多个组件
- default:document,
- slider:slider,
- },
- meta:{
- index:2,
- login:true // 标识 这句话的意思就是说当我们去访问这个导航的时候, 只有你登陆的时候才能展示对应的组件,
- }
- },
6. 怎么用呢具体? 也就是说在我们进入导航的时候, 他会执行这个 beforeEach 这么一个导航钩子,
- router.beforeEach((to,from,next)=>{
- //console.log("beforeEach")
- //console.log("bv")
- // next()
可以在这里面进行判断,
拿到目标导航的这么一个信息, 就是 to, 如果说 to.meta.login 为 true, 说明要去登陆, 需要登陆的话就把他重定向到我们登陆的一个页面上去,
next() 里面写上要登陆的路径
- })
- router.beforeEach((to,from,next)=>{
- //console.log("beforeEach")
- //console.log("bv")
- //next()
- if(to.meta.login){
- next('/login') // 打开页面 ---- 移动到 document 导航上时, http://localhost:8080/login 重定向到 login 上了,(准备 login 组件, 把他渲染出来就可以了)
- }else{
- next()
- }
- })
所以说我们就可以使用这样一个方式, 在每一个导航里面添加一个这样的信息,
- meta:{
- index:2,
- login:true // 标识 这句话的意思就是说当我们去访问这个导航的时候, 只有你登陆的时候才能展示对应的组件,
- }
标识一下他是需要登陆的, 在我们进入组件之前, 我们可以拿到这个标识 to.meta.login, 判断一下它是否需要登陆,
如果需要登陆, 我们就把他重定向到 login 这个导航上去,
如果不需要登陆, 直接进入到组件里面, next()
7. 进入导航之前, 我们可以执行这样一个导航钩子,
- router.beforeEach((to,from,next)=>{
- //console.log("beforeEach")
- //console.log("bv")
- // next()
- })
进入导航之后, 也给我 i 我们提供给了导航钩子,
- /* 进入导航之后 ---- 两个参数 */
- router.afterEach((to,from)=>{
在这里我们可以做什么事情呢?---- 改变导航, title 也改变
有的时候需要, 有的时候不需要, 所以我们判断一下,
- if(to.meta.title){ /* 如果 title 存在 */
- window.document.title = to.meta.title
- }else{
- window.document.title = 'miaov'
- }
- })
- meta:{
- index:3,
- title:'user' // 配置 title 数据
- }
- 8.
进入前:
- router.beforeEach((to,from,next)=>{
- // 判断是否登陆
- })
进入后:
- router.afterEach((to,from)=>{
- // 改变 title
- })
9. 以上两个钩子函数, 它其实是全局的钩子函数, 只要你切换导航, 这两个钩子函数都会被触发,
那我们现在不想设置全局的, 而是当我们访问到具体某一个导航时再让它触发具体某一个导航的钩子函数,
怎么写?
也就是说我们不需要全局的, 在具体某一个路由信息里面去配置,
10. 注释掉全局的导航钩子函数, 当我们访问到 document 里面的时候需要做些判断, 那这时候
我们进入之前我们需要去做些事情, 它给我们提供了一个导航钩子函数, beforeEnter(){}
- {
- path:'/document',
- name:'document',
- beforeEnter(){
- console.log('beforeEnter') // 进入到页面中发现, 只有当你访问 document 时才会执行钩子函数, 打印 beforeEnter
- next()
- },
- //component:document // 一个路由对应一个组件
- components:{ // 一个路由对应多个组件
- default:document,
- slider:slider,
- },
- meta:{
- index:2,
- login:true,
- title:'document'
- }
- },
- 11.
beforeEnter(to,from,next){} 也是接受三个参数,
next() 决定你是否要进入导航,
15. 组件级钩子函数
1. 现在我们可以在某一个单独的路由里面设置一个钩子函数, 也可以在全局设置, 那我们能不能在组件里面设置的呢?
我们可以在组件里面去设置, 它也给我们提供了相对应的钩子函数,
比如说我们在 about.vue 组件里面,
当我进入组件之前, 它其实执行了一个路由钩子函数,
在 about.vue 中, 做如下设置:
- <script>
- export default {
- beforeRouteEnter(){
- console.log('beforeRouterEnter') /* 进入到页面中发现, 只有当你访问 about 时才会执行钩子函数, 打印 beforeRouterEnter*/
- next() // 来控制是否进入此导航
- }
- }
- </script>
2. 注意一个东西, this 问题, 比如说我们现在制造一个场景, 也就是说我们在组件里面有这个数据, 当我们访问这个组件的时候呢,
那我们执行 beforeRouteEnter, 然后在里面把数据给改了,
- <script>
- export default {
- data(){
- return{
- test:'改变前'
- }
- },
- beforeRouteEnter(to,from,next){
- console.log('beforeRouterEnter') /* 进入到页面中发现, 只有当你访问 about 时才会执行钩子函数, 打印 beforeRouterEnter*/
- console.log(this) // 未定义
- next((vm)=>{ /*next 里面接受一个回掉函数, vm 就是当前实例 */
- vm.test='改变了'
- })
- }
- }
- </script>
3. 在 about.vue 中还有二级导航 study,work,hobby
当我们切换二级导航的时候, 二级导航渲染的数据我是 stydy, 我是 work, 我是 hobby, 其实是变了,
但是我们 about.vue 这个组件是不是复用的, 也就是说它只会生成一次, 那现在我在 about.vue 这个组件里面去切换这些二级导航,
那我怎么知道你这个导航它更新了呢?
这个时候呢, 它其实给我们提供了一个钩子函数, 当我们在一个组件里面有二级导航时, 我点击二级导航, 实际上现在我们导航更新了, 那么
它就会触发我们的钩子函数,
当我们组件更新之后, 它执行了一个导航钩子函数,
- beforeRouteUpdate(to,from,next){
- console.log('beforeRouteUpdate')
- next()
- }
4. 现在我么有了两个导航钩子, 一个就是我们进入的导航钩子 ------- 我们可以控制下是否要进入这个导航里面,
一个是当我们点击二级导航的时候, 我们把这个导航给更新了, 我们也可以控制下你是否去进行更新, 是否进入到我们二级导航里面,
5. 现在比如说我在 about.vue 里面, 当我切换到 document.vue 里面的时候, 我 about.vue 里面有些数据还没有完成,
那这时候我们不让它切换到 document.vue 里面.
也就是说在 about.vue 里面我们组织它切换到 document.vue 里面, 那么是不是要知道我们什么时候离开这个导航?
这个时候我们看一下它会执行什么样的钩子函数?
当我们离开组件的时候, 他会执行一个钩子函数, 叫做,
- beforeRouteLeave(to,from,next){
- console.log('beforeRouteLeave')
- next() // 不写 next(), 就不会离开这个组件
- }
- 6.
来源: http://www.qdfuns.com/article/39070/8076d4b459935c7794cc32ed84712c07.html