前端路由

看到这里可能有朋友有疑惑了,前端也有路由吗?这些难道不应该是在后端部分操作的吗?确实是这样,但是现在前后端分离后,加上现在的前端框架的实用性,为的就是均衡前后端的工作量,所以在前端也有了路由,减轻了服务器对这方面的判断,在前端做好路由分发之后,后端就只需要写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%;
            width: 60%;
            height: 100px;
            background: purple;
            color: white;
            border: 1px solid rgb(144, 143, 143);
            text-align: center;
            line-height: 50px;
        }
        .mcommon{
            margin-top: 2%;
            width: 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就到这里,我把经常用到的知识点都揉在一起了,篇幅有点长,耐心看吧,其实都挺简单的,只是有些地方稍微注意一下就行

vue(5)—— vue的路由插件—vue-router 常用属性方法的更多相关文章

  1. [ vue ] quasar框架踩坑:在vue文件外导入路由,执行router.push('/')没有效果

    问题描述: 1. 如图所示的项目结构目录, axios.js 文件负责拦截全局请求和回复,我在拦截回复的代码中写了:如果服务器回复了一个401错误,则执行Router.push('/'),但是该方法失 ...

  2. Vue图片懒加载插件 - vue lazyload的简单使用

    Vue module for lazyloading images in your applications. Some of goals of this project worth noting i ...

  3. Vue(三)之前端路由

    01-前端路由 1.前端路由的实现原理 vue+vue-router 主要来做单页面应用(Single Page Application) 为什么我们要做单页面应用? (1)传统的开发方式 url改变 ...

  4. vue生成路由实例, 使用单个vue文件模板生成路由

    一.vue-loader与vue-router配合 $ cnpm install vue-router --save 二.生成vue-webpack模板 $ vue init webpack-simp ...

  5. 转AngularJS路由插件

    AngularJS学习笔记--002--Angular JS路由插件ui.router源码解析 标签: angular源码angularjs 2016-05-04 13:14 916人阅读 评论(0) ...

  6. [Vue 牛刀小试]:第十二章 - 使用 Vue Router 实现 Vue 中的前端路由控制

    一.前言 前端路由是什么?如果你之前从事的是后端的工作,或者虽然有接触前端,但是并没有使用到单页面应用的话,这个概念对你来说还是会很陌生的.那么,为什么会在单页面应用中存在这么一个概念,以及,前端路由 ...

  7. [Vue 牛刀小试]:第十三章 - Vue Router 基础使用再探(命名路由、命名视图、路由传参)

    一.前言 在上一章的学习中,我们简单介绍了前端路由的概念,以及如何在 Vue 中通过使用 Vue Router 来实现我们的前端路由.但是在实际使用中,我们经常会遇到路由传参.或者一个页面是由多个组件 ...

  8. vue学习指南:第十一篇(详细) - Vue的 路由 第一篇 ( router )

    一.路由的配置 路由  vue-router 1. 什么是路由? 路由相当于一个配置对象 路由:就是我们通过不同的url访问不同的内容,通过angular.js 可以实现多视图的单页,现在流行的单页面 ...

  9. 「Vue」起步 - vue-router路由与页面间导航

    vue-router 我们知道路由定义了一系列访问的地址规则,路由引擎根据这些规则匹配找到对应的处理页面,然后将请求转发给页进行处理.可以说所有的后端开发都是这样做的,而前端路由是不存在"请 ...

随机推荐

  1. 第一章 渲染调度来龙去脉——插入自己的shader

    总有人会问,这个或者那个功能怎么弄,或者看到别人做了什么酷炫的效果也想仿造.其实,功能的实现无非两种: 1.调用Cesium现有的API组合实现:往往照猫画虎,还存在性能不过关的问题,绕了半天其实终究 ...

  2. Linux 用户及权限详解

    Linux 用户及权限详解 用户 , 组 ,权限 安全上下文(secure context): 权限: r,w,x 文件: r : 可读,可以使用类似cat 等命令查看文件内容. w : 可写,可以编 ...

  3. 统一修改表单参数(表单提交的空字符串统一转null)

    统一修改表单参数(表单提交的空字符串统一转null) 1.介绍: 我们业务中有时会遇到提交的表单中某个参数为空字符串,导致后台接受的为空字符串("")而不是我们理想中的null,会 ...

  4. 每日分享!~ JavaScript中面试基础--1,数组检测的方式 2.传统事件绑定和W3C标准绑定事件的区别~

    javaScript 那些方式中检测数据类型 typeof typeof isNaN // 结果是function 检测数组的几种方式 instanceof arr instanceof Array( ...

  5. Python中路径操作

    目录 1. os.path模块 2. pathlib模块 2.1 目录操作 2.2 文件操作 3. shutil模块 3.1 os模块 3.2 shutil模块 1. os.path模块 3.4版本之 ...

  6. .NET Core微服务之基于Ocelot实现API网关服务

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.啥是API网关? API 网关一般放到微服务的最前端,并且要让API 网关变成由应用所发起的每个请求的入口.这样就可以明显的简化客户端 ...

  7. Android多Module下的Application引用方式

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 Android开发时,Application一般都放在APP中,Lib模块如果想引用Application则需要在APP中进行传递, ...

  8. Python:os 模块常用方法简介

    返回当前工作目录 os.getcwd() 返回 path 的绝对路径 os.path.abspath(path) os.path.abspath('.') 相当于 os.getcwd() 分割目录和文 ...

  9. Asp.Net Core 轻松学-利用 Swagger 自动生成接口文档

    前言     目前市场上主流的开发模式,几乎清一色的前后端分离方式,作为服务端开发人员,我们有义务提供给各个客户端良好的开发文档,以方便对接,减少沟通时间,提高开发效率:对于开发人员来说,编写接口文档 ...

  10. C#枚举的简单使用

    枚举这个名词大家都听过,很多小伙伴也使用过, 那么枚举在开发中能做什么,使用它后能给程序代码带来什么改变,为什么用枚举. 各位看官且坐下,听我一一道来. 为什么使用枚举? 1.枚举能够使代码更加清晰, ...