• 427 单页面应用,vue路由


    单页面应用程序

    • SPA : Single Page Application 单页面应用程序

    • MPA : Multiple Page Application 多页面应用程序

    • 单页 web 应用

      就是只有一个 web 页面的应用,
      是加载单个 HTML 页面,
      并在用户与应用程序交互时, 动态更新该页面的 web 应用程序

    • 区别

      • 对于传统的多页面应用程序来说, 每次请求服务器返回的都是一个完整的页面

      • 对于单页应用程序来说,

        只有第一次会加载页面,以后的每次请求,仅仅是获取必要的数据.然后,由页面中 js 解析获取的数据,展示在页面中

    • 单页面优势 :

      1. 减少了请求体积,加快页面响应速度,降低了对服务器的压力
      2. 更好的用户体验,让用户在 web app 感受 native app 的流畅, (局部刷新)
    • 单页面劣势 :

      1. 开发成本高 (需要学习路由)
      2. 不利于 SEO
    • 演示 : https://music.163.com/


    零、路由介绍

    • 路由 : 是浏览器 URL 中的哈希值( // hash) 与 展示视图内容 之间的对应规则。
      • 简单来说,路由就是一套映射规则(一对一的对应规则), 由开发人员制定规则.
      • 当 URL 中的哈希值( // hash) 发生改变后,路由会根据制定好的规则, 展示对应的视图内容
    • 为什么要学习路由?
      • 在 web App 中, 经常会出现通过一个页面来展示和管理整个应用的功能.
      • SPA 往往是功能复杂的应用,为了有效管理所有视图内容,前端路由 应运而生.
    • vue 中的路由 : 是 hashcomponent 的对应关系, 一个哈希值对应一个组件

    一、路由的基本使用

    准备工作 (3个)

    • 安装npm i vue-router
    • 引入
    <script src="./vue.js"></script>
    // 千万注意 :引入路由一定要在引入vue之后,因为vue-router是基于vue工作的
    <script src="./node_modules/vue-router/dist/vue-router.js"></script>
    
    • 实例路由对象 + 挂载到vue上
      • 实例路由对象 : const router = new VueRouter()
      • 挂载到vue上 : new Vue({ router,data,methods })
      • 验证路由是否挂载成功, 就看打开页面,最后面有没有个 ///

    具体步骤 (4个)

    • 1.入口
    • 2.路由规则
    • 3.组件
    • 4.出口
    // 1. 入口
    	 // 方式1 : url地址为入口   调试开发用
    	 输入url地址 改变哈希值 `01-路由的基本使用.html///one`	
    	 // 方式2 : 声明式导航 : router-link+to (见下面介绍)
         
    // 2. 路由规则
    // path : 路由路径 【path的属性值前面要加斜杠/。】
    // component : 将来要展示的路由组件
    routes: [
    	// 【path的属性值前面要加斜杠/。】
        { path: '/one', component: One }, 
        { path: '/two', component: Two }
    ]
    
    // 3. 组件
    // 使用返回值的这个组件名称
    const One = Vue.component('one', {
      template: ` <div> 子组件 one </div> `
    })
    
    // 4. 出口
    <!--  出口 组件要展示的地方-->
    <router-view></router-view>
    
    // 总结
    拿到入口哈希路径, 根据路由匹配规则,找到对应的组件,显示到对应的出口位置 
    

    01-路由的基本使用.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <!-- 
            准备工作 (3个)
            1. 安装路由 npm i vue-router
            2. 引入路由
            3. 实例化路由 + 挂载到vue上
            
            具体步骤 (4个)
            1. 入口  (哈希值) 手动在url上写  /one
            2. 规则  routes 
            3. 组件 
            4. 出口
        -->
    
        <div id="app">
            <!-- 第四步 : 出口 占位置 【出口router-view在哪里,就在哪里显示组件。】【vue-router.js中内置了vueRouter】 -->
            <router-view></router-view>
        </div>
    
        <script src="./vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
        <script>
            // 第三步 : 路由组件 【路由组件要写在路由实例对象前,否则报错。】
            const One = {
                template: `<div>one组件</div>`
            }
    
            // 实例化路由
            const router = new VueRouter({
                // 第二步 : 路由的匹配规则 一个哈希值 对应一个组件
                routes: [{
                    path: '/one',
                    component: One
                }]
            })
    
            const vm = new Vue({
                router,
                el: '//app',
                data: {}
            })
        </script>
    </body>
    
    </html>
    

    image-20200320094316086


    二、路由使用注意事项

    • 入口
      • 最常用的入口 是 声明式导航 router-link
    <!-- 
        router-link 组件最终渲染为 a标签, to属性转化为 a标签的href属性 
        to 属性的值 , 实际上就是哈希值,将来要参与路由规则中进行与组件匹配
        <a href="///one" class="">ONE</a>
    -->
    <router-link to="/one">首页</router-link>  
    
    • 组件
    const One = {
      template: `<div> 子组件 one </div> `
    }
    
    • 演示 : 多个组件匹配
    <div id="app">
      <!-- 1 路由入口:链接导航 -->
      <router-link to="/one">One</router-link>
      <router-link to="/two">Two</router-link>
    
      <!-- 4 路由出口:用来展示匹配路由视图内容 -->
      <router-view></router-view>
    </div>
    
    <!--  导入 vue.js -->
    <script src="./vue.js"></script>
    <!--  导入 路由文件 -->
    <script src="./node_modules/vue-router/dist/vue-router.js"></script>
    <script>
      // 3 创建两个组件
      const One ={
        template: '<h1>这是 one 组件</h1>'
      }
      const Two =  {
        template: '<h1>这是 two 组件</h1>'
      }
    
      // 0 创建路由对象
      const router = new VueRouter({
        // 2. 路由规则
        routes: [
          { path: '/one', component: One },
          { path: '/two', component: Two }
        ]
      })
    
      const vm = new Vue({
        el: '//app',
        //0. 不要忘记,将路由与vue实例关联到一起!
        router
      })
    </script>
    

    02-多个路径.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <!-- 
            准备工作
            1. 安装
            2. 引入
            3. 实例化+挂载
    
            具体步骤
            1. 入口
            2. 规则
            3. 组件
            4. 出口
        -->
    
        <div id="app">
            <!-- 第一步 : 入口 
                1. 刚才手动写 测试.开发时候用   /one   /two
                2. 声明式导航
            -->
    
            <!-- 
                router-link 声明式导航 
                router-link 最终会编译成 a 标签 
                to 转化为href 
                作用 : 改变入口的哈希值路径
            -->
    
            <!-- 最后编译成 <a href="///one" class="">ONE</a> -->
            <router-link to="/one">ONE</router-link>
            <!-- <router-link to="/two">TWO</router-link> -->
    
            <!-- 第四步 :出口 -->
            <router-view></router-view>
        </div>
    
        <script src="./vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
        <script>
            // 第三步 : 组件
            const One = {
                template: `<div>one组件</div>`
            }
            const Two = {
                template: `<div>two组件</div>`
            }
    
            // 实例化路由
            const router = new VueRouter({
                // 规则
                routes: [{
                    path: '/one',
                    component: One
                }, {
                    path: '/two',
                    component: Two
                }]
            })
    
            const vm = new Vue({
                router,
                el: '//app',
                data: {}
            })
        </script>
    </body>
    
    </html>
    

    三、入口导航菜单高亮处理

    • 点击导航 => 元素里添加了两个类
    <a href="///one" class="router-link-exact-active router-link-active">One</a>
    <a href="///two" class="">Two</a>
    
    • 修改方式1 : 直接修改类的样式
    .router-link-exact-active,
    .router-link-active {
      color: red;
      font-size: 50px;
    }
    
    
    • 修改方式2 : 使用存在过的类样式 => 修改默认高亮类名
    const router = new VueRouter({
      routes: [],
      // 修改默认高亮的a标签的类名
      // red 是已经存在过的
      linkActiveClass: 'red'
    })
    
    

    03-高亮状态.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    
        <style>
            /* 假如说路由是后面加进来的, 但是如果之前就已经有了一个类 */
            
            .red {
                color: red;
                font-size: 50px;
            }
            /* 
            .router-link-exact-active,
            .router-link-active {
                color: red;
                font-size: 50px;
            } 
            */
        </style>
    </head>
    
    <body>
        <div id="app">
            <!-- 1. 入口 -->
            <router-link to="/one">one</router-link>
            <router-link to="/two">two</router-link>
    
            <!-- 4. 出口 -->
            <router-view></router-view>
        </div>
        <script src="./vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
        <script>
            // 3. 组件
            const One = {
                template: `<div>one组件</div>`
            }
            const Two = {
                template: `<div>two组件</div>`
            }
    
            //  实例化
            const router = new VueRouter({
                // 2. 规则
                routes: [{
                    path: '/one',
                    component: One
                }, {
                    path: '/two',
                    component: Two
                }],
                // router-link-exact-active 【去掉router-,改为小驼峰,最后加上Class。】
                linkExactActiveClass: 'red'
            })
    
            const vm = new Vue({
                router,
                el: '//app',
                data: {}
            })
        </script>
    </body>
    
    </html>
    
    

    04-高亮状态-精确匹配和模糊匹配.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    
        <style>
            /* 假如说路由是后面加进来的 ,但是如果之前就已经有了一个类 */
            /* .red {
                color: red;
                font-size: 50px;
            } */
            
            .router-link-exact-active,
            .router-link-active {
                color: red;
                font-size: 50px;
            }
        </style>
    </head>
    
    <body>
        <!-- 
           1. 精确匹配  和 模糊匹配  (了解)
           2. router-link-exact-active: 精确匹配   当url上的路径 == href的值 
           3. router-link-active      : 模糊匹配   当url上的路径 (包含)>=  href的值
         -->
    
        <div id="app">
            <!-- 1. 入口 -->
            <!-- exact:加上表示只允许精确匹配,不允许模糊匹配 【只需给没有精确路由的router-link 加上 exact 即可。】-->
            <router-link to="/" exact>one</router-link>
            <router-link to="/two">two</router-link>
    
            <!-- 4. 出口 -->
            <router-view></router-view>
        </div>
    
        <script src="./vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
        <script>
            // 3. 组件
            const One = {
                template: `<div>one组件</div>`
            }
            const Two = {
                template: `<div>two组件</div>`
            }
    
            //  实例化
            const router = new VueRouter({
                // 2. 规则
                routes: [{
                        path: '/',
                        component: One
                    }, {
                        path: '/two',
                        component: Two
                    }]
                    // router-link-exact-active
                    // linkExactActiveClass: 'red'
            })
    
            const vm = new Vue({
                router,
                el: '#app',
                data: {}
            })
        </script>
    </body>
    
    </html>
    
    

    四、路由配置

    4.1 动态路由 => 详情列表

    导入 : 列表三个手机都要点击进去详情页, 只需要一个组件,显示不同的数据即可

    // 入口
    <router-link to="/detail/1">手机1</router-link>
    <router-link to="/detail/2">手机2</router-link>
    <router-link to="/detail/3">手机3</router-link>
    
    <router-link to="/detail">手机4</router-link>  没有参数如何????
    
    // 规则
    routes: [
      // 2 . 路由规则
      { path: '/detail/:id?', component: Detail }
    ]
    
    // 获取参数的三种方式
    const Detail =  {
        template: `
            // 方式1 : 组件中直接读取  
            //【$route:当前路由】
            <div> 显示详情页内容....{{ $route.params.id  }} </div>
        `,
        created() {
            // 方式2 : js直接读取
            // 打印只会打印一次,因为组件是复用的,每次进来钩子函数只会执行一次  
            // 【$route:当前路由】
            console.log(this.$route.params.id)
        },
        // 方式3 : 监听路由的参数,为什么不需要深度监听,因为一个路径变化,就会对应一个对新的路由对象(地址变)
        watch: {
            $route(to, from) {
                console.log(to.params.id)
            }
        }
    }
    
    

    05-动态路由-详情页.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <!-- 
           动态路由
           1. 使用参数接收不同的路由参数  
            path ='/detail/:id'  
           2. 参数可传可不传  path ='/detail/:id?' 
         -->
    
        <div id="app">
            <!-- 1. 入口 -->
            <router-link to="/detail/1">手机1</router-link>
            <router-link to="/detail/2">手机2</router-link>
            <router-link to="/detail/3">手机3</router-link>
            <router-link to="/detail">手机4</router-link>
    
            <!-- 4. 出口 -->
            <router-view></router-view>
        </div>
    
        <script src="./vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
        <script>
            // 3. 组件
            const detail = {
                // 经测试,在生命周期钩子函数中,要使用$route,前面得加this. ,否则报错,因为是事件;而在组件的其他地方,可加可不加
                template: `<div>详情页组件 {{ $route.params.id }}</div>`
            }
    
            //  实例化
            const router = new VueRouter({
                // 2. 规则
                routes: [{
                    path: '/detail/:id?',
                    component: detail
                }]
            })
    
            const vm = new Vue({
                router,
                el: '#app',
                data: {}
            })
        </script>
    </body>
    
    </html>
    
    

    4.2 路由对象 - $route

    image-20200320145914241

    image-20200320150335970

    image-20200320152559208


    • 一个路由对象 (route object) :表示当前激活的路由的状态信息,包含了当前 URL 解析得到的信息

    • 一个哈希值路径 ==> 一个路由对象

    • $route.path

      • 类型: string
      • 字符串,对应当前路由的路径,总是解析为绝对路径,如 "/foo/bar"
      • // 后面、?前面的内容
    • $route.params

      • 类型: Object
      • 一个 key/value 对象,包含了动态片段和全匹配片段,如果没有路由参数,就是一个空对象。
    • $route.query

      • 类型: Object
      • 参数对象
      • 一个 key/value 对象,表示 URL 查询参数。例如,对于路径 /foo?user=1,则有 $route.query.user == 1,如果没有查询参数,则是个空对象。
    • $route.hash

      • 类型: string

        当前路由的 hash 值 (带 //) ,如果没有 hash 值,则为空字符串。

    • $route.fullPath

      • 类型: string
      • 全路径
      • 完成解析后的 URL,包含查询参数和 hash 的完整路径。
    // 演示 : 
    <router-link to="/detail/4?age=21//one">detail</router-link>
    { path: '/detail/:id?', component: detail } 
    在组件内 created打印 this.$route
    > fullPath: "/detail/4?id=001//one"
    > hash : "//one"
    > params : {id:'4'}
    > query : {age : 21}
    > path : '/detail/4'
    
    

    06-$route.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <!-- 
           $route:路由对象,解析的url信息,哈希值的url信息
           哈希值 (#/one/4?age=30#aaa) ==> $route 
         -->
        <div id="app">
            <!-- 1. 入口 -->
            <!-- <router-link to="/one/4?age=30#aaa">one</router-link> -->
            <router-link to="/one/1">第一个</router-link>
            <router-link to="/one/2">第二个</router-link>
    
            <!-- 4. 出口 -->
            <router-view></router-view>
        </div>
    
        <script src="./vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
        <script>
            // 3. 组件
            const One = {
                template: `<div>one组件 {{ $route.params.id }}</div>`,
                // 经测试,在生命周期钩子函数中,要使用$route,前面得加this. ,否则报错,因为是事件;而在组件的其他地方,可加可不加
                created() {
                    // 页面加载过程中的第一次的值,不会变化,因为created只执行一次
                    console.warn(this.$route.params.id)
                },
                // 补充mounted、updated
                // mounted不能监听到 this.$route.params.id 的变化
                mounted() {
                    console.log('mounted中的id是---', this.$route.params.id)
                },
                // updated能监听到 this.$route.params.id 的变化
                updated() {
                    console.log('updated中的id是---', this.$route.params.id)
                },
                // 很重要的思想(★)
                // 使用watch 监听 $route 路由对象,获取里面的信息 【url变了,$route跟着变。之前监听复杂类型时,是复杂类型的地址没变,只是它里面的数据变化了而已。】
                watch: {
                    $route(newVal) {
                        console.warn(newVal)
                        console.warn(newVal.params.id)
                    }
                }
            }
    
            //  实例化
            const router = new VueRouter({
                // 2. 规则
                routes: [{
                    path: '/one/:id',
                    component: One
                }]
            })
    
            const vm = new Vue({
                router,
                el: '#app',
                data: {}
            })
        </script>
    </body>
    
    </html>
    
    

    4.3 嵌套路由/子路由: children

    导入 : url测试 parent 和child, 想让child 在 parent 中显示

    • parent 的内部 添加 : <router-view> </router-view>
    • 规则里添加 children
    • /child 和 child 的区别
      • 如果是/child => 那么访问就可以直接访问///child就可以访问 子组件
      • 如果是child => 那么访问就应该访问///parent/child才可以访问子组件
    const parent = {
        template: `<p>parent  <router-view> </router-view> </p>`
    }
    const child = {
        template: `<p>child</p>`
    } 
    
    const router = new VueRouter({
        routes: [
            {
                path: '/parent',
                component: parent,
                children: [
                    { path: '/child', component: child }
                ]
            }
        ]
    })
    
    

    07-嵌套路由.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <div id="app">
            <!-- 1. 入口 -->
            <!-- 
                需求: child组件 放到 parent组件 里面
                办法: children: [路由规则]
            -->
    
            <!-- 4. 出口 -->
            <router-view></router-view>
            <hr />
        </div>
    
        <script src="./vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
        
        <script>
            // 3. 组件
            const parent = {
                template: `<div> parent组件 -- <router-view></router-view> </div>`
            }
    
            const child = {
                template: `<div>child组件</div>`
            }
    
            //  实例化
            const router = new VueRouter({
                // 2. 规则
                routes: [{
                    path: '/parent',
                    component: parent,
                    children: [{
                        // 子组件的path值前,加斜杆/,则浏览器的url中不需要写成 /parent/child,直接写/child即可。不加的话,就要写成 /parent/child
                        path: '/child',
                        component: child
                    }],
                    // children: [{
                    //     path: 'child',
                    //     component: child
                    // }]
    
                    //  path : '/child'    => 哈希值 : /child
                    //  path : 'child'     => 哈希值 : /parent/child
                }]
            })
    
            const vm = new Vue({
                router,
                el: '#app',
                data: {}
            })
        </script>
    </body>
    
    </html>
    
    

    4.4 命名路由 ==> :to="{ name : 'xxx' }"

    • 有时候,通过一个名称来标识一个路由显得更方便一些,
    • 特别是在链接一个路由,或者是执行一些跳转的时候。 ===> 场景
    • 你可以在创建 Router 实例的时候,在 routes 配置中给某个路由设置名称。 ==> 如何命名
    // 命名
    routes: [
        {
            path: '/parent',
            name: 'parent',
            component: parent
        }
    ]
    
    // 入口链接 + 跳转  (使用 path 和 name 的转换)
    <!-- 方式1 : url手动写 -->
    
    <!-- 方式2 : 入口链接 声明式导航 -->
    <router-link to="/parent">点击</router-link>
    <router-link :to="{ name : 'parent' }">点击</router-link>  // 忘了 带 : 原始对象类型
    
    <!-- 方式3 : 编程式导航 -->
     fn() {
         // this.$router.push('/parent')
         this.$router.push({
             name: 'parent'
         })
     }
    
    

    09-命名路由.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <div id="app">
            <!-- 1. 入口 -->
            <!-- 下面两个用的都是 path -->
            <!-- 
                <router-link to="/one">one</router-link>
                <router-link to="/two">two</router-link> 
            -->
            <!-- to前面不加冒号,就会把属性值当做字符串 -->
            <router-link :to="{ name : 'one' }">one</router-link>
            <router-link :to="{ name :'two' }">two</router-link>
    
            <!-- 4. 出口 -->
            <router-view></router-view>
        </div>
    
        <script src="./vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
    
        <script>
            // 3. 组件
            const One = {
                template: `<div>one组件</div>`
            }
            const Two = {
                template: `<div>two组件</div>`,
                created() {
                    console.log(this.$route.name)
                }
            }
    
            //  实例化
            const router = new VueRouter({
                // 2. 规则
                routes: [{
                    path: '/one',
                    name: 'one',
                    component: One
                }, {
                    path: '/two',
                    name: 'two',
                    component: Two
                }]
            })
    
            const vm = new Vue({
                router,
                el: '//app',
                data: {}
            })
        </script>
    </body>
    
    </html>
    
    

    4.5 命名视图:

    导入 : 有时候想同时 (同级) 展示多个视图,

    需求 : 访问 / 根目录 同时展示以下三个组件

    • 三个组件
    const header = {
        template: `<p>header  </p>`
    }
    const main = {
        template: `<p>main  </p>`
    }
    const footer = {
        template: `<p>footer  </p>`
    }
    
    
    • 规则
    // 以前的那个方式只能显示三个 header
    // 演示之前的效果 
    
    routes: [
        {
            path: '/',
            components: {
                default: header,
                m: main,
                f: footer
            }
        }
    ]
    
    
    • 出口
    <router-view> </router-view>
    <router-view name="m"> </router-view>
    <router-view name="f"> </router-view>
    
    

    08-命名视图.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <!-- 
           需求 :  /  => 三个组件 header main footer
         -->
        <div id="app">
            <!-- 4. 出口 -->
            <router-view></router-view>
            <router-view name="m"></router-view>
            <router-view name="f"></router-view>
        </div>
        
        <script src="./vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
        <script>
            // 3. 组件
            const header = {
                template: `<div>header组件</div>`
            }
            const main = {
                template: `<div>main组件</div>`
            }
            const footer = {
                template: `<div>footer组件</div>`
            }
    
            //  实例化
            const router = new VueRouter({
                // 2. 规则
                routes: [{
                    path: '/',
                    components: {
                        default: header,
                        m: main,
                        f: footer
                    }
                }]
            })
    
            const vm = new Vue({
                router,
                el: '//app',
                data: {}
            })
        </script>
    </body>
    
    </html>
    
    

    4.6 重定向

    方式1:
    redirect: '/header'
    
    方式2:
    redirect: { name: 'header' }
    
    方式3:【函数,用路由对象去判断, to:即路由对象$route。】
    redirect: to => {
          // console.log(to)
        return {
            name: 'about'
        }
    }
    
    

    10-重定向.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <div id="app">
            <!-- 1. 入口 -->
            <!-- <router-link to="/one">one</router-link> -->
    
            <!-- 4. 出口 -->
            <router-view></router-view>
        </div>
        <script src="./vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
        <script>
            // 3. 组件
            const One = {
                template: `<div>one组件</div>`
            }
    
            //  实例化
            const router = new VueRouter({
                // 2. 规则
                routes: [
                    // 方式1 : path路径
                    {
                        path: '/',
                        redirect: '/one'
                    },
    
                    // 方式2 : 路由的名称
                    {
                        path: '/',
                        redirect: {
                            name: 'one'
                        }
                    },
    
                    // 方式3 : 函数,用路由对象去判断
                    {
                        path: '/',
                        // to:即路由对象$route
                        redirect: to => {
                            // console.log(to) // to:即路由对象$route
                            //  if (to.XXX) {
                            //    return { name : 'one'}
                            //  } else {
                            //    return {name : 'two' }
                            //  }
    
                            return {
                                name: 'one'
                            }
                        }
                    }, {
                        path: '/one',
                        name: 'one',
                        component: One
                    }
                ]
            })
    
            const vm = new Vue({
                router,
                el: '#app',
                data: {}
            })
        </script>
    </body>
    
    </html>
    
    

    4.7 【路由给】组件传参

    【路由给组件传参】

    • 原始方式使用 $route获取
    // 入口
    <router-link to="/header/3">123</router-link>
    
    // 规则
    routes: [
        {
            path: '/header/:id',
            component: header,
        }
    ]
    
    // 获取参数
    const header = {
        template: `<p>header  {{ $route.params.id }}  </p>`
    }
    
    
    • 布尔模式
    // 入口
    <router-link to="/header/3">123</router-link>
    
    // 规则
    routes: [
        {
            path: '/header/:id',
            component: header,
            // 如果 props 被设置为 true,route.params 将会被设置为组件属性
            props: true
        }
    ]
    
    // 获取参数
    const header = {
        // 参数 id 当成参数
        props: ['id'],
        template: `<p>header   {{ id }} </p>`
    }
    
    
    • 对象模式
    // 入口
     <router-link to="/header">123</router-link>
    
    // 规则
     routes: [
         {
             path: '/header',
             component: header,
             props: { foo: '0000' }
         }
     ]
    // 组件
     const header = {
            props: ['foo'],
            template: `<p>header   {{ foo }} </p>`
     }
    
    
    • 函数模式
    // 同对象模式一样
    // 区别是props值不一样
     props: to => {
         return { foo: '0000' }
     }
    
    
    • 注意 : 对象模式和函数模式参数 在props里,所以声明式导航那里就不要传参了

    11-组件传参.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <!-- 
           方式1:to='/one/4'  path='/one/:id?'  
                  组件:$route.params.id 
                  事件:this.$route.params.id 
    
           方式2: 布尔模式  
                  路由规则里,写props:true     
                  将参数id 作为组件的属性存在  
                  -  props: true
                  - 组件内 : props:['id']
                  - 使用: {{ id }}
    
           方式3: 对象模式      
                  - props : { aaa : 'bbb' }
                  - props: ['aaa']
                  - {{ aaa }}
    
            方式4 :  函数模式    
                   - props : to => { return { aaa : 'ccc' }  }
                   - props:['aaa']
                   - {{ aaa }} 
        -->
    
        <div id="app">
            <!-- 1. 入口 -->
            <!-- <router-link to="/one/11">one</router-link> -->
            <router-link to="/one">one</router-link>
    
            <!-- 4. 出口 -->
            <router-view></router-view>
        </div>
        <script src="./vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
        <script>
            // 3. 组件
            const One = {
                props: ['id', 'aaa'],
                template: `<div>one组件 {{ aaa }}</div>`
            }
    
            //  实例化
            const router = new VueRouter({
                // 2. 规则
    
                routes: [
                    // props : true  将id参数作为组件的属性存在
                    // {
                    //     path: '/one/:id',
                    //     component: One,
                    //     props: true
                    // }
    
                    // 将aaa 作为 组件的属性存在
                    // {
                    //     path: '/one',
                    //     component: One,
                    //     props: {
                    //         aaa: 'bbb'
                    //     }
                    // }
    
                    // 函数
                    {
                        path: '/one',
                        component: One,
                        props: to => {
                            return {
                                aaa: 'ccc'
                            }
                        }
                    }
                ]
            })
    
            const vm = new Vue({
                router,
                el: '#app',
                data: {}
            })
        </script>
    </body>
    
    </html>
    
    

    五、路由进阶

    5.1 元信息

    • **作用 **
    在路由导航的时候,可以用作判断
    
    
    • 规则声明
     routes: [
         {
             path: '/header',
             component: header,
             // (1)meta默认是空对象;(2)可以控制组件的显示与隐藏
             meta: {
                title: 'XXXX'
             }
         }
     ]
    
    
    • 获取
     created() {
        document.title = this.$route.meta.title
     }
    
    

    01-元信息.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <!-- 
            3个准备工作
            4个具体步骤
    
            元信息 : 路由里添加 meta 字段 
        -->
    
        <div id="app">
            <router-view></router-view>
            <h1 id="haha">哈哈</h1>
            <h1>嘿嘿</h1>
        </div>
    
        <script src="./vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
    
        <script>
            //组件
            const One = {
                template: `<div>one组件</div>`,
                created() {
                    // 有了这个meta 可以做很多事情
                    // console.log(this.$route.meta.title)
                    // 可以设置标题
                    document.title = this.$route.meta.title
                    console.log(document.querySelector('//haha').innerHTML) // 哈哈
                    console.log(111) // 111
                }
            }
    
            const Two = {
                template: `<div>two组件</div>`,
                created() {
                    document.title = this.$route.meta.title
                }
            }
    
            // 实例化 + 挂载
            const router = new VueRouter({
                routes: [{
                    path: '/one',
                    name: 'one',
                    component: One,
                    meta: {
                        title: '帅气的马哥'
                    }
                }, {
                    path: '/two',
                    name: 'two',
                    component: Two,
                    meta: {
                        title: '骚气的春春'
                    }
                }]
            })
    
            const vm = new Vue({
                router,
                el: '//app',
                data: {}
            })
        </script>
    </body>
    
    </html>
    
    

    image-20200321083610233


    5.2 编程式导航

    const one = {
        template: ` 
    <div> <button @click="handleClick('back')">返回 上一页</button>
    <button @click="handleClick('push')">跳转 two页</button>
    <button @click="handleClick('replace')">替换 two页</button> 
    </div>`,
        methods: {
            handleClick(type) {
                if (type == 'back') {
                    // 返回
                    this.$router.back()
                } else if (type == 'push') {
                    // 跳转 有历史记录
                    this.$router.push('/two')
                } else {
                    // 替换 没有历史记录
                    this.$router.replace('/two')
                }
            }
        }
    }
    const two = {
        template: `<p>two </p>`
    }
    
    

    02-编程式导航.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <!-- 
          入口 
          1. 手动url修改   /one
          2. 声明式导航  <router-link to='/one'>one</router-link>
    
          3. 编程式导航  this.$router.push('/one')
              (1)前进(跳转) ==> 
                - this.$router.push()    - 有记录 【可以后退】
                - this.$router.replace() - 没有记录 【不可以后退】
              (2)返回   ====> this.$router.back()
        -->
    
        <div id="app">
            <router-view></router-view>
        </div>
    
        <script src="./vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
        <script>
            //组件
            const One = {
                template: `<div> one组件
                    <button @click="handle('push')"> 跳转到two - push </button>
                    <button @click="handle('back')"> 返回到/ </button>
                    <button @click="handle('replace')"> 跳转到two - replace </button>
                </div>`,
    
                methods: {
                    handle(type) {
                        if (type == 'push') {
                            // $route: 路由对象,解析url信息 (属性:.path、 .name、 .meta、 .params)
                            // $router: VueRouter的路由实例【 也就是下面的const router = new VueRouter(...)的变量router 】,挂载到vue实例上后,就是$router,用于编程式导航 (方法 ) 
                            // push => 有记录的 【这里的push是vue的跳转,不是原生js的】
                            this.$router.push('/two')
                        } else if (type == 'back') {
                            this.$router.back()
                        } else if (type == 'replace') {
                            // replace => 没有记录的
                            this.$router.replace('/two')
                        }
                    }
                }
            }
    
            const Two = {
                template: `<div>two组件</div>`
            }
    
            // 实例化 + 挂载
            const router = new VueRouter({
                routes: [{
                    path: '/one',
                    name: 'one',
                    component: One
                }, {
                    path: '/two',
                    name: 'two',
                    component: Two
                }]
            })
    
            const vm = new Vue({
                router,
                el: '#app',
                data: {}
            })
        </script>
    </body>
    
    </html>
    
    

    5.3 导航守卫

    router.beforeEach((to, from, next) => {
        // 访问 login
    
        if (to.name == 'login') {
            // 下一步
            next()
        } else {
            // 停止跳转
            next(false)
            // 跳转到下一步
            next({ name: 'login' }) 或者 使用路径  next('/login')
        }
    })
    
    

    03-导航守卫.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <!-- 
            导航守卫   : 是通过跳转或者取消的方式守卫导航   A => 导航守卫 =>  B
    
            需求 : 所有的页面经过登录 之后才准访问
                1.  =>  login   可以
                2.  =>  one    =>  访问login => 登录之后 => one
    
            前置导航守卫   beforeEach   
            概念 :  是通过跳转或者取消的方式守卫导航   拦截
            1. 写法  router.beforeEach( (to,from ,next)=> {} )
            2. to : 目标路由对象  from : 来源路由对象  next: 下一步
            3. next() 允许下一步
                next(false) 不允许
                next('/login')  跳转到login    
        -->
    
        <div id="app">
            <router-view></router-view>
        </div>
    
        <script src="./vue.js"></script>
        <script src="./node_modules/vue-router/dist/vue-router.js"></script>
    
        <script>
            //组件
            const One = {
                template: `<div>one组件</div>`
            }
            const Login = {
                template: `<div>Login组件</div>`
            }
    
            // 实例化 + 挂载
            const router = new VueRouter({
                routes: [{
                    path: '/one',
                    name: 'one',
                    component: One
                }, {
                    path: '/login',
                    name: 'login',
                    component: Login
                }]
            })
    
            // 导航守卫
            // /one => /login
            // to : 目标路由对象($route)
            // from : 来源路由对象
            // next():下一步 【不写next(),就不能访问下一步。】
            router.beforeEach((to, from, next) => {
                // console.log('from:', from)
                console.log('to:', to)
    
                // 如果访问 login => 允许访问 next 【用to.name、to.path都可以。】
                if (to.name == 'login') {
                    next() //  next()中不用传递路径 '/login',否则会无限循环,直到报错。
                } else if (to.name == 'one') {
                    next()
                } else {
                    next(false); // 不允许访问,next(false) 和不写任何代码的结果一样
                    // next('/login'); // 如果不是login => 转到 login
                    // next({ name: 'login' })
                }
            })
    
            const vm = new Vue({
                router, // 挂载
                el: '#app',
                data: {}
            })
        </script>
    </body>
    
    </html>
    
    
  • 相关阅读:
    MySQL百万级、千万级数据多表关联SQL语句调优
    不就是SELECT COUNT语句吗,居然有这么多学问
    分布式锁讲解
    Java 中堆和栈的区别
    Java中的回调机制
    在Eclipse上Maven环境配置使用
    项目忽然出现 The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path 解决方法
    HttpServletResponse
    com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
    深入浅出java常量池
  • 原文地址:https://www.cnblogs.com/jianjie/p/12605571.html
Copyright © 2020-2023  润新知