• vue系列教程-11vuerouter路由


    本内容为系列内容,全部内容请看我的vue教程分类

    什么是路由

    大家还记得我最开始提到的spa单页面吗,通过不同的路径显示不同的组件,这个就是通过router实现的

    那么首先我们还需要引入一个 router文件

    <script src="https://cdn.bootcss.com/vue-router/3.1.3/vue-router.js"></script>
    

    这里的话我们还是以上面的bilibili消息中心为示例,使用到刚刚的代码

    还是先定义组件模板

    <template id="writeback">
        <div>
            <div>回复我的</div>
            <div>这是回复我的界面</div>
        </div>
    </template>
    <template id="aite">
        <div>
            <div>@我的</div>
            <div>这是@我的界面</div>
        </div>
    </template>
    <template id="zan">
        <div>
            <div>收到的赞</div>
            <div>这是收到赞的界面</div>
        </div>
    </template>
    

    然后定义组件

    const writeback = {
        template: '#writeback'
    }
    const aite = {
        template: '#aite'
    }
    const zan = {
        template: '#zan'
    }
    

    基础使用

    在组件那一节我们是通过动态组件来实现界面切换的,这里我们就使用路由来实现页面切换

    这里我们实例化vue的时候,属性里面的 router传入一个 VueRouter 的实例,这个数组routes就是详细的路径和对应的组件信息,比如我们浏览器访问 www.lookroot.cn/writeback的时候,页面就展示上面定义好的 writeback组件

    let vm = new Vue({
        el: '#app',
        data() {
        },
        router: new VueRouter({
            routes: [
                {
                    path: '/writeback',
                    component: writeback
                },
                {
                    path: '/aite',
                    component: aite
                },
                {
                    path: '/zan',
                    component: zan
                },
            ],
        })
    })
    

    那么原本的导航也要进行修改 这个 router-link就会在页面中渲染成a标签,作为导航

    <div class="bili-leftnav">
        <ul>
            <li>
                <router-link to="/writeback">回复我的</router-link>
            </li>
            <li>
                <router-link to="/aite">@我的</router-link>
            </li>
            <li>
                <router-link to="/zan">收到赞的</router-link>
            </li>
        </ul>
    </div>
    

    那么我们原本的选中效果是没有了的因为没有绑定点击事件,但是路由会给默认激活的导航加上一个class名为router-link-active ,我们简单编写一下

     /* 当前显示路由的颜色 */
     .bili-content .bili-leftnav li .router-link-active {
         color: #2fbbea;
     }
    

    然后和动态组件一样要有个展示的容器吧,这里我们也给它加上过渡动画,这个router-view就是路由界面的展示容器和动态组件的component是一样的

    <div class="bili-rightcontent">
        <transition enter-active-class="animated fadeInDown" leave-active-class="animated fadeInUp"
            mode="out-in" :duration="200">
            <router-view></router-view>
        </transition>
    </div>
    

    好的这就完成了改造了看看效果吧完全是可以的,注意看路径的变化

    vue教程-lookroot

    路由重定向

    如果我们打开这个界面的时候,路径后面没有跟着具体的路径,界面就不会显示任何的组件,这肯定是不友好的

    必须设置一个默认界面,我们咋路由配置文件里面增加一个路由信息

    {
        path: '/',
        redirect: '/writeback',
    },
    

    这里的意思就是,默认为初始界面的时候,就重定向到 writeback这个路径,这样writeback就成了默认界面了

    命名视图和命名路由

    命名视图

    如果我们页面中同时有两个的时候,点开页面要展示两个组件,那么你怎么知道哪个组件应该展示到哪个 view里面呢?这就是命名视图

    我们在添加一个 view,并且namecommon

    <div class="bili-rightcontent">
        <transition enter-active-class="animated fadeInDown" leave-active-class="animated fadeInUp"
            mode="out-in" :duration="200">
            <router-view></router-view>
        </transition>
        <router-view  name="common"></router-view>
    </div>
    

    定义一个组件模板

    <template id="vuefooter">
        <div>
            <h2>footer</h2>
        </div>
    </template>
    

    定义这个组件

    const vuefooter = {
        template: '#vuefooter'
    }
    

    然后修改一下 writeback的路由配置,component就换成components了,并且默认的容器展示writeback组件,命名为common的容器展示 刚刚定义的这个vuefooter组件

    {
        path: '/writeback',//点击的路径
        // 命名视图
        components: {
            default: writeback,
            common: vuefooter
        },
    },
    

    看看效果,是可以的,这就是命名视图

    vue教程-lookroot

    命名路由

    我们给路由也起名字,这样方便使用,这里还是以 writeback为例

    {
        path: '/writeback',//点击的路径
        // 命名视图
        components: {
            default: writeback,
            common: vuefooter
        },
        // 命名路由
        name: 'writeback',
    },
    

    修改它的导航链接,这样就完成了

    <router-link :to="{name:'writeback'}">回复我的</router-link>
    

    嵌套路由和路由传参

    这个嵌套大家就知道了,肯定是路由中有路由,就像组件中有组件一样,又是套娃行为

    来看下这个界面,1部分是导航,2部分是路由展示的组件同时相对于3部分又是一个导航,3部分是路由展示的组件,这就是一个很明显的路由嵌套,我们就来实现一下

    vue教程-lookroot

    首先我们要添加这个我的消息这个导航链接

     <div class="bili-leftnav">
         <ul>
             <li>
                 <router-link :to="{name:'writeback'}">回复我的</router-link>
             </li>
             <li>
                 <router-link to="/aite">@我的</router-link>
             </li>
             <li>
                 <router-link to="/zan">收到赞的</router-link>
             </li>
             <li>
                 <router-link to="/mymsg">我的消息</router-link>
             </li>
         </ul>
     </div>
    

    然后定义第二部分和第三部分的组件

    这个第二部分的组件模板,它里面首先是一个导航,这个导航我循环渲染出来的,模拟了十个用户聊天导航,并且是使用了 :to也就是绑定动态的路径,路径后面跟上了 index也就是把当前是第几个用户传递给第三部分这就是路由传参params方式

    路由传参params方式

    <template id="mymsg">
        <div>
            <div>消息</div>
            <div>
                <ul>
                    <ol v-for="index in 10" >
                        <router-link :to="'/mymsg/msgcontent/'+index">用户{{index}}</router-link>
                    </ol>
                </ul>
                <router-view></router-view>
            </div>
        </div>
    </template>
    

    定义第三部分组件模板

    <template id="msgcontent">
        <div>
            这是和用户{{id}}具体的消息界面
        </div>
    </template>
    

    定义这两个组件,为什么要使用 props来接受传值那?下面解释

    //第二部分组件
    const mymsg = {
        template: '#mymsg',
    }
    //第三部分组件
    const msgcontent = {
        template: '#msgcontent',
        props: ['index'],
    }
    

    嵌套路由

    然后定义这个嵌套路由,这个 mymsg就是第二部分的路由配置,然后给它配置一个children这里面就是嵌套的路由配置了,首先path后面的 :id就是匹配我们上面定义的router-link传参的index,这个props: true就是将我们传递的index值,自动注册为第三部分组件的 props

    // 嵌套路由
    {
        path: '/mymsg',
        component: mymsg,
        children: [{
            path: 'msgcontent/:index',
            component: msgcontent,
            props: true
        }]
    }
    

    看下效果,这就完成了

    vue教程-lookroot

    路由传参query方式

    我们回到前面的第一部分的导航,修改一下这个我得消息的导航,使用?连接传递值

    <router-link to="/mymsg?username=lookroot">我的消息</router-link>
    

    如果我们不适用上面的props来接受传值该怎么做呢?

    修改一下组件定义,created周期时使用this.$route.query来接受query方式的传值,赋值给username

    const mymsg = {
        template: '#mymsg',
        data() {
            return {
                username: ''
            }
        },
        created() {
            // query传值
            this.username = this.$route.query.username
        },
    }
    

    然后在组件模板中渲染这个数据

    <template id="msgcontent">
        <div>
            这是和用户{{id}}具体的消息界面
        </div>
    </template>
    

    看下效果是可以的

    vue教程-lookroot

    @

    路由模式

    路由有两种模式historyhash模式,默认也就是我们前面使用的模式是hash模式

    这种模式就是在后面跟着一长串,不是很好看,如果追求美观就可以使用history模式

    来实例一下

    定义两个组件模板

    <template id="page1">
        <div>
            page1
        </div>
    </template>
    <template id="page2">
        <div>
            page2
        </div>
    </template>
    

    定义这两个组件

    const page1 = {
        template: '#page1',
    }
    const page2 = {
        template: '#page2',
    }
    

    实例化一个router,指定modehistory模式

     const router = new VueRouter({
         mode: 'history',
         routes: [
             {
                 path: '/',
                 redirect: '/page1',
             },
             {
                 path: '/page1',
                 component: page1,
                 name: 'page1',
             },
             {
                 path: '/page2',
                 component: page2,
                 name: 'page2',
             },
         ],
     });
    

    在页面中定义导航,这里我们介绍另外一种路由跳转的方式编程式的导航

    <div id="app">
        <!-- <router-link to="/page1">page1</router-link> -->
        <button @click="gotoPage('/page1')">page1</button>
        <button @click="gotoPage('/page2')">page2</button>
        <router-view></router-view>
    </div>
    

    那么这里都绑定上一个点击事件,然后传递一个地址字符串

    编程式的导航

    在当前组件(父组件)中编写一下这个点击事件,使用this.$router.push进行路由跳转

    methods: {
        gotoPage(path) {
            // 编程式的导航 
            this.$router.push(path)
        }
    },
    

    运行一下查看效果,看下导航栏地址是不是就美观多了啊

    vue教程-lookroot

    但是这个模式有问题的,比如我们直接在浏览器中打开这个链接是会报错的

    vue教程-lookroot

    解决这个问题的方法需要后端处理官网文档

    全局路由守卫

    顾明思议,守卫嘛,就是拦截放行的效果

    这里我们举一个登录的示例,但只是简单的举例哦,真实开发并不是这样做的

    首先我们在vue的原型指向上挂载一个属性,用来记录用户是否登录

    Vue.prototype.isLogin = false
    

    然后编写,第三个组件 login,并添加一个login点击事件

    <template id="login">
        <div>
            <button @click="login">login</button>
        </div>
    </template>
    

    然后定义这个组件,并编写点击事件,点击就修改isLogin的值为 true,并使用this.$router.back返回上一个页面

    const login = {
        template: '#login',
        methods: {
            login() {
                Vue.prototype.isLogin = true;
                //返回的意思
                this.$router.back();
            }
        },
    }
    

    然后配置路由信息

    {
        path: '/login',
        component: login,
        name: 'login'
    },
    

    好的定义全局守卫,记住要在定义router之后 to, from, next也不用解释吧,语义化的,前置守卫顾名思义也就是执行之前会调用的,所以我们在这里进行判断用户是否登录,如果未登录,我们就挑战到 命名路由为login这个路由地址

     // 全局的 前置守卫
     router.beforeEach((to, from, next) => {
             if (!Vue.prototype.isLogin) {
                 next({
                     name: 'login'
                 });
             } else {
                 next();
             }
     })
    

    效果就是我们点击切换路由的时候,如果没有登录,就跳转到登录页面,但是这里大家仔细想这样一个问题,我的login路由同样也会执行守卫,同样我也没有登录,然后他就会再次跳转,这样就成了死循环,怎么解决这个问题呢?

    路由元信息

    我们简单修改一下路由配置,我们在需要判断登录的路由中加上meta: { isLogin: true },表明当前路由是需要登录的

    routes: [
        {
            path: '/',
            redirect: '/page1',
            meta: { isLogin: true }
        },
        {
            path: '/page1',
            component: page1,
            name: 'page1',
            meta: { isLogin: true }
        },
        {
            path: '/page2',
            component: page2,
            name: 'page2',
            meta: { isLogin: true }
        },
        {
            path: '/login',
            component: login,
            name: 'login'
        },
    ],
    

    然后我们怎么在路由守卫中读取这个字段那?

    我们修改一下这个守卫,matched是路由记录,那么我们就在要到达的路由中进行查找字段to.matched.some(item => item.meta.isLogin)如果有这个字段的才进行判断

     router.beforeEach((to, from, next) => {
         // matched 路由记录
         if (to.matched.some(item => item.meta.isLogin)) {
             if (!Vue.prototype.isLogin) {
                 next({
                     name: 'login'
                 });
             } else {
                 next();
             }
         } else {
             // 执行下一个钩子
             next();
         }
     })
    

    然后我们在else里面执行 next();就是执行下一个钩子,也就是放行的意思

    测试一下看看效果,我们先把mode改为hash方便测试,可以看到要先点击login才能进行访问

    vue教程-lookroot

    组件内的路由守卫

    大家记得有些网页你点击后退或者其他,会弹出提示 是否确定离开吗?

    我们来实践一下,修改一下 page1的组件定义,在beforeRouteLeave的钩子里面进行判断

    const page1 = {
        template: '#page1',
        beforeRouteLeave(to, from, next) {
            const result = window.confirm('确定离开页面吗?将不会保存')
            if (result) {
                next()
            } else {
                next(false)
            }
        }
    }
    

    vue教程-lookroot

    那么还有其他更多的路由参数,这里就不一一讲解了

  • 相关阅读:
    20180925-5 代码规范,结对要求
    20180925-6 四则运算试题生成
    20180925-7 规格说明书-吉林市2日游
    第二周例行报告
    第二周博客作业
    【杨老师粉丝群】第一周立会报告第四次
    20180925-1 每周例行报告
    规格说明书——吉林市两日游
    效能分析
    四则运算试题生成
  • 原文地址:https://www.cnblogs.com/lookroot/p/13184063.html
Copyright © 2020-2023  润新知