zoukankan      html  css  js  c++  java
  • vue(5)—— vue的路由插件—vue-router 常用属性方法

    前端路由

    看到这里可能有朋友有疑惑了,前端也有路由吗?这些难道不应该是在后端部分操作的吗?确实是这样,但是现在前后端分离后,加上现在的前端框架的实用性,为的就是均衡前后端的工作量,所以在前端也有了路由,减轻了服务器对这方面的判断,在前端做好路由分发之后,后端就只需要写API接口了,更着重于数据交互,逻辑上的代码编写了

    单页面应用

    那么,既然有前端路由,每个路由是不是都要单写一个页面呢?不需要的,现在都提倡单页面应用

    什么是单页面应用呢

    单页面应用,即 single page application ,简称SPA ,所有的路由其实都只在一个页面上完成,这种就叫单页面应用,我们不需要每个路由对应一个页面去编写

    为什么要用单页面应用

    1.传统的根据路由切换页面,都是立即切换,如果切换的网络资源很多的话,加载需要很久,用户体验很不好,并且写的页面越多,也越不好管理,可能还会有很多重复的代码出现,到后期更新迭代后,页面越来越多,这样会产生更多的资源

    2.SPA可以完美解决以上的问题,并且数据切换时只是局部切换,且并不会立即切换,而是在某个合适的时间用ajax异步请求后端的API接口,再加载出数据,这里的【某个合适的时间】是指:因为用户查看网页的时候并不会永远都在切换页面吧?所以在某个刚好的时间切换就行了

    单页面应用的原理

    原理就是运用了锚点,即html页面上的id属性,因为id用的符号【#】,根据前面的web前端基础开发,相信你已经可以理解了,比如一个页面右边的固定按钮,返回顶部,比如这里淘宝的页面,这个返回顶部的按钮

    用的就是【#】,这个就不多介绍了,因为学到vue这里,前面说过的,你得有钱端的基础知识才更容易学。在js里【#】其实是hash值,比如这个例子:

    因为js自带有location对象,在我点击登录时,因为用onhashchange监听了hash改变,所以立马可以得到新的hash值,然后按逻辑把数据渲染出来

    代码:

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <title></title>
    
        <style>
    
        </style>
    </head>
    
    <body>
        <a href='#/login'>登录</a>
        <a href="#/register">注册</a>
        <div id="app">
    
        </div>
        <!-- <script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script> -->
        <script>
            var point = document.getElementById('app');
    
            window.onhashchange = function () {
                console.log(location);
                switch (location.hash) {
                case '#/login':
                    point.innerHTML = '<h2>登录</h2>'
                    break;
                case '#/register':
                    point.innerHTML = '<h2>注册</h2>'
                    break;
                default:
                    break;
                }
            }
        </script>
    </body>
    
    </html>
    原生js的路由控制

    总之在单页面应用里,用【#】的意思是当前页面根本就没有跳转,还是当前的页面,只是用了一些机制把数据换掉了而已,这个机制就是vue-router,vue-router其实就是用了这个onhash的原理,不过比js原生的多了很多特性和功能

    注:

    • 锚点值即a标签的跳转,hash
    • onhashchange获取url上锚点的改变
    • location.hash指当前的锚点
    • js里也有switch的用法

    vue-router

    vue-router插件位置:

     官方文档传送门:点我

    vue-router简介

    这里说下,为什么要截图官方的文档,直接去官方文档看不就好了吗对吧,原因是:vue-router更新版本很快,所以文档也会跟着更新,有些知识点可能有些不一样。加上也就不用切换到另一个界面看了再回来看了,我截的图也只是个人觉得需要注意的点

    安装vue-router

    安装之后当前目录下多了个vue-router文件夹:

    引入vue-router包

    引入本地包 

    你可以引入你下载的本地的,真正的使用vue-router是和vue配套一起使用的,所以vue也得引入

    引入cdn包

    查看控制台如果没报错表示引入成功

    引入cdn包代码: 

    <script type="text/javascript" src='https://unpkg.com/vue-router/dist/vue-router.js'></script>
    
    <!-- 或者引入指定的版本 -->
    <script type="text/javascript" src='https://unpkg.com/vue-router@2.0.0/dist/vue-router.js'></script>

    使用vue-router 

    使用步骤:

    1.引入vue-router插件
    2.让根元素Vue载入自定义的VueRouter对象(此对象由vue-route插件提供,插件最后会返回一个VueRouter对象和router-linke和router-view组件),方面后面使用
    3.创建、配置一个router对象,里面设定好不同的锚点值对应的路由以及对应好第二步里自定义的VueRoter对象
    4.将创建好的router对象挂载到vue实例对象上,直接如上写即可,如果报错什么matched,一定是根元素Vue里没有写入router

    5.利用vue-router插件提供的两个全局的组件<router-link>和<router-view>设定好DOM布局,通过<router-link>组件的to属性设定好路由路径,且组件最后会被渲染成a标签,<router-view>给定一个路由组件的出口,用于让VueRouter对象进行数据渲染
    6.根据不同的路由,渲染整个页面,最后展示出来

    注意:

    当使用vue-router时,挂载组件只需要再VueRouter对象里挂载就行了,不需要再在vue实例对象里用components属性挂载了

    VueRouter定义路由组件的属性是routes,不是router,定义的url属性用path

    定义的url路由不用手动写上【#】,vue-router会自动添加上

    以上就是vue-router的简单使用

    命名路由

    vue的路由也可以命名的,是不是感觉越来越像一门后端语言了,哈哈

    注:

    使用命名路由,在定义路由组件内部,最好用v-bind绑定,添加一个name属性,值则为你定义的路由名字,必须是字典形式:{name:'名字'}

     

    我这里试了下,不用绑定直接使用也可以,以前的版本不行的,现在的貌似可以,具体还有待研究,我使用的版本:vue2.6.9,vue-router3.0.2

    代码

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <title></title>
    
        <style>
    
        </style>
    </head>
    
    <body>
        <div id="app">
        </div>
        <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
        <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
        <script>
            Vue.use(VueRouter) // 目前是全局状态,可有可不有
            var Vlogin = {  template: `<div>登录</div>` }
            var Vregister = { template: `<div>注册</div>` }
            const router = new VueRouter({
                routes: [{
                        path: '/login',
                        name:'login',
                        component: Vlogin  },
                    {
                        path: '/register',
                        name:'register',
                        component: Vregister
                    }]
            })
            var Vcom = {
                template: `<div>
                    <router-link :to="{name:'login'}">登录页面</router-link>
                    <router-link :to="{name:'register'}">注册页面</router-link>
                    <router-view></router-view></div>`
            }
            let app = new Vue({
                el: '#app',
                components: {  Vcom  },
                router,
                template: `<Vcom />`
            })
        </script>
    </body>
    
    </html>
    vue-router 命名路由

    默认路由 

    给默认的路由,因为很多时候打开页面,总要展示一个默认的页面吧,所以如下:给路由组件添加一个 '/',然后指向一个你觉得可以作为默认页面的组件就行

    补充一下,在vue-router3.0.1版本中,还有这种写法:

    但是由于我目前的是3.0.2,所有效果没出来,并且我感觉没多大用啊,反正都是渲染,直接用官方的就行了,搞些新写法整那么花里胡哨干嘛对吧? 

    路由重定向

    这个跟上面的默认路由很类似,只是用的是redirect属性:


    我这里访问页面会自动跳转到登录页面,这种就是路由重定向

    代码:

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <title></title>
    
        <style>
    
        </style>
    </head>
    
    <body>
        <div id="app">
        </div>
        <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
        <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
        <script>
            Vue.use(VueRouter) // 目前是全局状态,可有可不有
            var Vlogin = {
                template: `<div>登录</div>`
            }
            var Vregister = {
                template: `<div>注册</div>`
            }
            const router = new VueRouter({
                routes: [{
                        path:'/',
                        redirect:'/login'
                    },
                    {
                        path: '/login',
                        component: Vlogin
                    },
                    {
                        path: '/register',
                        component: Vregister
                    }
                ]
            })
            var Vcom = {
                template: `<div>
                    <router-link to="/login">登录页面</router-link>
                    <router-link to="/register">注册页面</router-link>
                    <router-view></router-view>
                    </div>`
            }
            let app = new Vue({
                el: '#app',
                components: {
                    Vcom
                },
                router,
                template: `<Vcom />`
            })
        </script>
    </body>
    
    </html>
    路由重定向

    带参数的路由

     我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染

    带参数是什么意思,比如就目前我这个博客园后台编辑页面:

    https://i.cnblogs.com/EditPosts.aspx?postid=10570774

    其中,【?】后面的postid=10...就是带的参数

    除了这种,还有这种:

    其中的p/105...就是参数,当然博客园的到底用的什么做的url路由就不得而知了,也与本文无关了。

    总之就是这种:xxx/user/userid/1,其中的userid/1就是参数

    总结下就是,有以下两种参数,表达的意思都是一样的,是为了找page等于多少的数据

    xxx.com/cont?page=2

    xxx.com/cont/page/1

    那么在实际开发中,肯定会有指定某个参数的访问,这种其实就是查询嘛,查询单个数据,也是非常常见且重要的,来个例子:

     (有些图片看着字很小或者又显示不全,你右键查看图片源地址可以看大图的,这个是博客园主题的关系,显示不全)

    注意:
    • 用【:】匹配的路由组件,path是这样:/page/:pid,有【/】分割,在匹配时用的params,就可以匹配  /page/1,/page/2,/page/3等等的,浏览器url上显示的是 /page/1
    • 另一种匹配,路由组件中的path没做任何改动,直接在匹配时用的query,就可以匹配  /page?pid=1,/page?pid=2,/page?pid=3等等的,浏览器url显示的是  /page?pid=1

    相关具体步骤:

    1.重新定义了两个局部组件,其中一个用  /page:pid  ,为什么这么写,这是官方文档里明确说明了的:

    2.再在router-link里多给了一个参数,params,在另外一个里添加了query:

    params和query都是固定的,不能随意更改,不信你可以改了试试。

    <router-link :to="{name:'pagep',params:{pid:1}}">第一页</router-link>   匹配对应前面的  xxx.com/cont/page/1
    <router-link :to="{name:'pageq',query:{pid:2}}">第二页</router-link>     匹配对应前面的 xxx.com/cont?page=2

    那有没有想过,它这就给个参数(params/query),为什么就可以匹配呢?匹配之后可以拿到那个参数吗?

    你可以用this.$router和this.$route查看下 ,为什么是这两个参数呢?因为读源码所得,当引入了vue-router之后,Vue实例化对象就多个两个恶属性,一个是$router,一个是$route

    如下,给了一个已创建的生命周期函数,在生命周期里打印了this.$router,发现就是VueRouter对象,里面有相关的属性

     再打印this.$route看看,发现用【:】 可以匹配url的参数(比如这里用的 :pid),并且给这个参数加了个键,然后匹配到的参数会进入params参数里去,作为一个字典存在:

    为什么要传给params呢?你想想,像这样的匹配,匹配到了之后,需要交给后端处理,那你怎么拿到这个参数并传递给后端呢?没有变量名字你怎么传?是不是需要一个形参啊?所以这里就有个params属性,它对应一个字典,字典key就是定义路由组件时path部分,冒号后面的字段,值就是匹配到的值,比如这里就是:{pid:'1'}。

    并且它还有个参数query,但是此时如上图,query还是一个空字典。

    也就是说这两个属性 query和params都是路由组件自带的属性,它本来就有的,所以知道为什么前面说在router-link绑定那里不能随意换成其他参数了吧

    关于这里,可能你理解起来有点吃力,如果你觉得比较吃力,得多看官方文档,传送门   多试几个例子,我个人感觉它那官方文档对于这里都没说的多清楚

    由于我是做Python开发的,因为Python的django框架里就有个路由匹配的参数 path('/page:int<pid>',func),其中的pid就可以类比成这里的pid,所以就很好理解,对这Python不熟悉的请忽略我说的Python这个部分

    那么有了用【:】匹配,再看另一个url为/page?pid=2是否能拿到值呢?是否会把参数作为键值交给自己自带的属性query呢:

    确实如此:

    那假如说我把两个router-link传进的参数不小心写错了,本来是params的写成query,本来是query写成了params,看是否可以拿到呢:

    拿是可以拿到,但是参数都进错了归属,这种操作太非主流了,可以是可以,但不建议这么干

    代码:

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <title></title>
        <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
        <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
    
        <style>
    
        </style>
    </head>
    
    <body>
            <body>
        <div id="app">
    
        </div>
        <script>
            Vue.use(VueRouter) // 目前是全局状态,可有可不有
            var Vpagep = {
                template: `<div>第一页内容</div>`,
                created() {
                    console.log(this.$route)
                },
            }
            var Vpageq = {
                template: `<div>第二页内容</div>`,
                created() {
                    console.log(this.$route)
                },
    
            }
            const router = new VueRouter({
                routes: [{
                        path: '/page/:pid',
                        name: 'pagep',
                        component: Vpagep
                    },
                    {
                        path: '/page',
                        name: 'pageq',
                        component: Vpageq
                    }
                ]
            })
            var Vcom = {
                template: `<div>
                    <router-link :to="{name:'pagep',query:{pid:1}}">第一页</router-link>
                    <router-link :to="{name:'pageq',params:{pid:2}}">第二页</router-link>
                    <router-view></router-view></div>`
            }
            let app = new Vue({
                el: '#app',
                components: {
                    Vcom
                },
                router,
                template: `<Vcom />`
            })
        </script>
    </body>
    
    </html>
    带参数的路由

    编程式导航

    编程式导航,听着那么高端大气,到底什么是编程式导航呢,官方文档解释:

    也就是说,编程式导航就是直接使用router实例的push方法,并且其实前面我们用的router-link组件最终其实也是用的这个push方法,换言之我们也可以直接使用这个push方法,自定义,自己编写导航,这就是编程式导航

    官网使用案例:

    // 字符串
    router.push('home')
    
    // 对象
    router.push({ path: 'home' })
    
    // 命名的路由
    router.push({ name: 'user', params: { userId: '123' }})
    
    // 带查询参数,变成 /register?plan=private
    router.push({ path: 'register', query: { plan: 'private' }})

    更多的就移步自己研究吧:点我

    说了半天好像还是不够深刻对吧?还是看例子:

    看懂了吧?说白了就是,利用一个事件,在这个事件里把由router-link组件换成了$router.push(),传进一个字典,字典和之前用的router-link传入的一样即可,这个字典就是name和params(或者是query) 

    push这个意思就很明显了,就是把这些参数推进去

    代码:

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <title></title>
        <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
        <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
    
        <style>
    
        </style>
    </head>
    
    <body>
            <body>
        <div id="app">
    
        </div>
        <script>
            Vue.use(VueRouter) // 目前是全局状态,可有可不有
            var Vpagep = {
                template: `<div>第一页内容</div>`,
                created() {
                    console.log(this.$route)
                },
                
            }
            var Vpageq = {
                template: `<div>第二页内容</div>`,
                created() {
                    console.log(this.$route)
                },
    
            }
            const router = new VueRouter({
                routes: [{
                        path: '/page/:pid',
                        name: 'pagep',
                        component: Vpagep
                    },
                    {
                        path: '/page',
                        name: 'pageq',
                        component: Vpageq
                    }
                ]
            })
            var Vcom = {
                template: `<div>
                    <button @click="firstHander">第一页</button>
                    <button @click="secondHander">第二页</button>
                    <router-view></router-view>
                    </div>`,
                methods:{
                    firstHander(){
                        this.$router.push( {name:'pagep',params:{'pid':1}} )
                    },
                    secondHander(){
                        this.$router.push( {name:'pageq',query:{'pid':2}} )
                    }
                }
            }
            let app = new Vue({
                el: '#app',
                components: {
                    Vcom
                },
                router,
                template: `<Vcom />`
            })
        </script>
    </body>
    
    </html>
    router-push

    嵌套路由

      

    因为路由组件之下,完全还有可能有细分的子路由组件之类的,这样就可以把整个页面切分成很多个模块,每个模块做着不同的分工,所以就需要有嵌套路由这个东西,

    然后用法和路由组件是一样的,就不用多说了,直接来个例子说明:

    先看这个百度首页,我圈出来的部分:

    百度首页和个人中心页面当做路由的根组件,把我圈出来的部分作为子路由嵌套嵌套到个人中心路由组件里:

    就是这么简单,反正路由组件该有的都得有就行了

    代码:

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <title></title>
        <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
        <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
    
        <style>
    
        </style>
    </head>
    
    <body>
    
        <body>
            <div id="app">
            </div>
            <script>
                Vue.use(VueRouter) // 目前是全局状态,可有可不有 
                var Myfollow = {
                    template: `<div>我的关注</div>`
                }
                var Navigate = {
                    template: `<div>导航</div>`
                }
                var Story = {
                    template: `<div>小说</div>`
                }
                var Commend = {
                    tepmalte: `<div>推荐</div>`
                }
                var Person = {
                    template: `<div>个人主页<br>                    
                        <router-link to="/Person/follow">我的关注</router-link>
                        <router-link to="/Person/navigate">导航</router-link>
                        <router-link to="/Person/story">小说</router-link>
                        <router-link to="/Person/commend">推荐</router-link>
                        <router-view></router-view></div>`
                }
                var Home = {
                    tempalte: `<div>百度首页</div>`
                }
                const router = new VueRouter({
                    routes: [{
                            path: '/Person',
                            component: Person,
                            children: [{
                                    path: '/Person/follow',
                                    component: Myfollow
                                },
                                {
                                    path: '/Person/story',
                                    component: Story
                                },
                                {
                                    path: '/Person/commend',
                                    component: Commend
                                },
                                {
                                    path: '/Person/navigate',
                                    component: Navigate
                                },
                            ]
                        },
                        {
                            path: '/home',
                            component: Home
                        }
                    ]
                })
                var Root = {
                    template: `<div>
                        <router-link to="/home">百度首页</router-link>
                        <router-link to="/Person">个人主页</router-link>
                        <router-view></router-view></div>`
                }
                const app = new Vue({
                    el: '#app',
                    router,
                    components: {
                        Root,
                    },
                    template: `<Root />`,
                })
            </script>
        </body>
    
    </html>
    嵌套路由

    子路由的path 

    唯一要注意的是,写子路由的path时,要嘛带上完整的路由:

    要嘛不要带/,直接给一个路由的相对路径,vue会自动拼写成完整路由,其他没做任何改变,一样可以显示:

     

    动态路由

    我画出来的那个【'$route'】这个要注意,后面我们会用到

    什么是动态路由呢,我个人觉得官网讲的太随意了, 你看了估计都看不太懂啥意思

    那么动态路由到底是什么呢?这么说吧,因为Vue是单页面应用,那么就会有很多公用路由组件部分对吧,那么这些公用组件部分会被多个组件使用,通常的方法就是把公用路由组件挂载成子组件,然后公用的部分显示,不同的部分做单独渲染或者说单独的覆盖数据就行。

    这意思感觉有点像是模板一样对吧?反正都是那一套模板,把数据放进去就行了,好的,不多说,直接上例子:

    先看个网站,稀土掘金的,这个也是个开发者社区,然后我标记出来的,1就是根路由,2就是子路由,3就是公用部分(这个是要账号登录状态才有的),不管我点2部分的路由的哪个标签,3永远都有的,而且没有变,切换的永远是3下面的数据,并且3下面的数据的css样式也是公用部分:

    好的,简单的模仿一个:

     (为了在一个页面显示,所以排版看着有点怪)

    看下控制台打印的结果:

    大概什么逻辑呢?就是相同部分都用同一个路由组件作为子组件,在父级路由的router-link里传入对应的标签参数,在公用路由组件里做下处理,把内容填充上就行,不再需要分别定义多个组件了。

    这个在实际开发中,可以再公用路由组件里做判断,如果是哪个子路由,数据就是什么样,做好不同的分类显示就行了,这里作为案例就没做那么详细真实了

    好的,至于这个  '$route'(to,form)  其中的'$route'到底是什么暂且不 谈了,详细的看官网了

    代码:

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <title></title>
        <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
        <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
    
        <style>
    
        </style>
    </head>
    
    <body>
    
        <body>
            <div id="app"></div>
            <script>
                Vue.use(VueRouter) // 目前是全局状态,可有可不有                       
                var Pins = {
                    template: ` <div>我是沸点</div>`
                }
                var common = { // 公用组件
                    data() {
                        return {
                            msg: ''
                        }
                    },
                    template: `<div>公用部分:发表  - 写文章 - 分享链接 
                        <div>{{msg}}</div></div>`,
                    created() {
                        this.msg = '(css样式结构,还没有数据)'
                    },
                    watch: {
                        '$route'(to, form) {
                            console.log(form);
                            console.log(to);
                            this.msg = `${this.$route.params.category} 相关内容内容内容.........`
                        }
                    }
                }
                var home = {
                    template: `<div>
                        <router-link :to="{name:'common',params:{category:'commend'}}">推荐</router-link>
                        <router-link :to="{name:'common',params:{category:'follow'}}">关注</router-link>
                        <router-link :to="{name:'common',params:{category:'android'}}">安卓</router-link>
                        <router-view></router-view></div>`,
                }
                // 注意路由挂载组件的先后顺序,先创建再在路由里挂载
                const router = new VueRouter({
                    routes: [{
                            path: '/home',
                            component: home,
                            children: [{
                                    path: '/',
                                    component: common
                                },
                                {
                                    path: '/home/:category',
                                    name: 'common',
                                    component: common
                                }
                            ]
                        },
                        {
                            path: '/pins',
                            name: 'pins',
                            component: Pins
                        }
                    ]
                })
                var com = {
                    template: `<div>
                        <router-link to="/home">首页</router-link>
                        <router-link to="/pins">沸点</router-link>
                        <router-view></router-view></div>`
                }
                const app = new Vue({
                    el: '#app',
                    components: {
                        com
                    },
                    router,
                    template: `<com/>`
                })
            </script>
        </body>
    
    </html>
    动态路由

    keep-alive的用法

    在路由组件中也可以用keep-alive,主要用途是对切换页面时组件的缓存,防止销毁创建增大开销

    这个在前面的局部组件也有用到的,不多说。用法就是在组件的出口前后加一个vue特殊的组件<keep-alive>包裹住即可

    其他没变只是在入口函数那里加了keep-alive组件

     全局前置守卫验证

     这个全局前置守卫在旧版的vue-router里名字叫全局守卫

    在开发中,按照常识,都知道,不同用户的权限是不一样的,然后能访问的路由也是不一样的,所以这就是权限,而作为权限验证,得有一套机制吧,这套机制就是全局守卫

    比如,某个网站,验证用户的登录状态,如果未登录就提示登陆,否则就进不了需要登录的网页,必须登录之后才可以查看网页,这种场景就可以用全局前置守卫

    相关的说明:

    上面这个说的什么意思呢,主要就是说,必须要调用next方法,不然的话会卡住 

    路由元信息

    首先呢,路由组件有一个元信息meta参数,这个参数就可以配置一些权限验证:

    这里给一个小demo,如下,这是优酷视频网的某个部分,上面是免费视频,下面是需要会员才能看的视频

    好的,就做个这种简单的出来:

    点击会员时,它会自动跳转到登录页面

    当我登录之后,会员页面显示:

    以上部分,在router-link传入参数部分,可能有朋友会想,唉,你这为什么要定义两个公用组件,都那一套啊,免费电影和会员部分都用一套公用组件多省事啊,确实啊,这样确实省事,其实最开始我就是这样的,但是因为都用一个公用组件,在不同根组件切换到子组件时,会有错乱,达不到我们的需要的效果,所以我定义了两个公用组件。并且针对两个组件,后期肯定还会有不同的配置的,所以这样会更好维护一点

    原理就是在定义路由时,给需要验证的路由配置原信息,加了个meta参数,这个参数是router对象自带的属性,我们可以随意定义键值进去:

    利用这个键值用beforeEach全局守卫在路由跳转时判断这个参数,如果为true则需要做验证,验证通过则next()为空放行,验证不通过则用next跳转,这里的next是个回调函数,有点编程式导航router.push的意思,此时这个beforeEach全局守卫其实也可以看出一个周期钩子函数

    对于验证登录状态,用了js自带的一个localStorage永久存储对象作为存储 :

    需要清除的话,右键那个那个file://,点clear就行,详细的就不多说了,自行查资料研究吧

     完整代码

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <title></title>
        <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
        <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
    
        <style>
            .common{
                margin-top: 2%;
                 60%;
                height: 100px;
                background: purple;
                color: white;
                border: 1px solid rgb(144, 143, 143); 
                text-align: center;
                line-height: 50px;
            }
            .mcommon{
                margin-top: 2%;
                 60%;
                height: 100px;
                background-color: rgb(9, 78, 108);
                color:white;
                border: 1px solid rgb(172, 168, 168);
                text-align: center;
                line-height: 50px;
            }
        </style>
    </head>
    
    <body>
    
        <body>
            <div id="app"></div>
            <script>
                Vue.use(VueRouter) // 目前是全局状态,可有可不有                       
                var login = {
                    data() {
                        return {
                            name: '',
                            pwd: ''
                        }
                    },
                    template: `<div>                    
                            <input type='text' v-model="name">
                            <input type='password' v-model='pwd'>
                            <button @click="loginHander" >登录</button>                    
                        </div>`,
                    methods: {
                        loginHander() {
                            localStorage.setItem('user', {
                                'name': this.name,
                                'pwd': this.pwd
                            })
                            this.$router.push({
                                path: '/member'
                            })
                        }
                    },
                }
                var common = { // 免费电影公用组件
                    data() {
                        return {
                            msg: ''
                        }
                    },
                    template: `<div class="common">免费电影公用部分:XXXXX 
                        <div>{{msg}}</div></div>`,
                    created() {
                        this.msg = '(css样式结构,还没有数据)'
                    },
                    watch: {
                        '$route'(to, form) {
                            console.log(form);
                            console.log(to);
                            this.msg = `${this.$route.params.category} 相关内容内容内容.........`
                        }
                    }
                }
                var mcommon = { // 会员电影公用组件
                    data() {
                        return {
                            msg: ''
                        }
                    },
                    template: `<div class="mcommon">会员电影公用部分:XXXXX 
                        <div>{{msg}}</div></div>`,
                    created() {
                        this.msg = '(css样式结构,还没有数据)'
                    },
                    watch: {
                        '$route'(to, form) {
                            console.log(form);
                            console.log(to);
                            this.msg = `${this.$route.params.category} 相关内容内容内容.........`
                        }
                    }
                }
    
    
    
                var movie = { // 免费视频
                    template: `<div>
                        <router-link :to="{name:'common',params:{category:'hollywood'}}">好莱坞</router-link>
                        <router-link :to="{name:'common',params:{category:'trailer'}}">预告片</router-link>
                        <router-link :to="{name:'common',params:{category:'online-movie'}}">网络电影</router-link>
                        <router-view></router-view></div>`,
                }
                var member = { // 会员视频
                    template: `<div>
                        <router-link :to="{name:'mcommon',params:{category:'lastest'}}">最新</router-link>
                        <router-link :to="{name:'mcommon',params:{category:'cinema'}}">院线大片</router-link>
                        <router-link :to="{name:'mcommon',params:{category:'exclusive'}}">独播强挡</router-link>
                        <router-link :to="{name:'mcommon',params:{category:'popluar'}}">热门纪实</router-link>
                        <router-link :to="{name:'mcommon',params:{category:'bbc'}}">BBC经典</router-link>
                        <router-link :to="{name:'mcommon',params:{category:'anime'}}">热血动漫</router-link>
                        <router-view></router-view></div>`,
                };
                // 注意路由挂载组件的先后顺序,先创建再在路由里挂载
                const router = new VueRouter({
                    routes: [{
                            path: '/movie',
                            component: movie,
                            children: [{
                                    path: '/',
                                    component: common
                                },
                                {
                                    path: '/movie/:category',
                                    name: 'common',
                                    component: common
                                }
                            ]
                        },
                        {
                            path: '/member',
                            component: member,
                            meta: {  // 带有该参数,表示需要认证
                                auth: true
                            },
                            children: [
                                // 有认证之后不能再加默认路由,因为加了默认路由之后自动跳到根目录,使认证失效
                                // {
                                //     path: '/',
                                //     component: mcommon
                                // },
                                {
                                    path: '/member/:category',
                                    name: 'mcommon',
                                    component: mcommon
                                }
                            ]
                        },
                        {
                            path: '/login',
                            component: login,
                            name: 'login'
                        }
                    ]
                })
    
                router.beforeEach((to, from, next) => {
                    // to and from are both route objects. must call `next`.
                    console.log(from);
                    console.log(to.meta.auth);
                    if (to.meta.auth) {
                        if (localStorage.getItem('user')) {
                            next()
                        } else {
                            next({
                                path: '/login'
                            })
                        }
                    } else {
                        next()
                    }
    
                })
    
                var com = {
                    template: `<div>
                        <router-link to="/movie">电影</router-link>
                        <router-link to="/member">会员</router-link>
                        <router-link to="/login">登录</router-link>
                        <keep-alive>
                        <router-view></router-view>
                        </keep-alive></div>`
    
                }
                const app = new Vue({
                    el: '#app',
                    components: {
                        com
                    },
                    router,
                    template: `<com/>`
                })
            </script>
        </body>
    
    </html>
    全局前置守卫,配合meta参数

      

    官方文档里其实还有一个路由内部的守卫是这个:beforeEnter,这个就自己研究了

    在vue-router的官方文档里,守卫一共有这么多,自己研究了

    补充

    如果你遇到这样的报错:

    检查你的组件,看template参数写对没有

    如果遇到路由匹配到了,但是url没有正常显示:

    路由组件如下,

    编程式导航部分:

    coursedetail部分:

    页面显示:

     这样虽然有显示,但是url不对,原因是参数匹配有误,路由组件用的参数名是courseId,在做编程式导航时用的参数是detailId,我上面已经标注出来了

     作如下改动,即可:

    页面正常显示:

    总结:

    vue-router就到这里,我把经常用到的知识点都揉在一起了,篇幅有点长,耐心看吧,其实都挺简单的,只是有些地方稍微注意一下就行

  • 相关阅读:
    模板
    总结
    关于log方线段树
    [ICPC2014 WF]Sensor Network
    背包问题总结
    NOIP2020微信步数
    NOIP2020移球游戏
    CF643D Bearish Fanpages
    CF685C Optimal Point
    论恋爱对学习的促进作用
  • 原文地址:https://www.cnblogs.com/Eeyhan/p/10570774.html
Copyright © 2011-2022 走看看