# 第八模块:前端VUE2-组件化开发

# 3.组件化开发

在开发过程中,我们可以将页面中 某一部分 的功能编写成一个组件,然后再在页面上进行引用。

  • 有利于划分功能模块的开发(HTML、CSS、JavaScript等相关代码都集成到组件中)。
  • 有利于重用

# 3.1 局部组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>=======当前页面=======</h1>
    {{name}}

    <h1>=======引入子组件=======</h1>
    <Demo></Demo>
    <Demo></Demo>
    <Bb></Bb>
    <Bb></Bb>
    <hr/>
    <Bb></Bb>
</div>
<script>
    //创建子组件
    const Demo = {
        data:function() {
            return {
                msg: '哈哈哈哈哈'
            }
        },
        template: `
            <div>
                <h1>{{msg}}</h1>
                <input type="text" v-model="msg"/>
                <input type="button" @click="showMeg" value="点我呀">
            </div>
        `,
        methods: {
            showMeg: function () {
                alert(this.msg);
            }
        }
    }

    //创建子组件
    const Bili = {
        // 组件中的data是一个方法,并返回值(与Vue对象创建不同)
        data:function() {
            return {
                dataList: [
                    {"id": 1, "title": "2022再见"},
                    {"id": 2, "title": "2023你好"},
                ]
            }
        },
        template: `
            <div>
                <h1>数据列表</h1>
                <table border="1">
                    <thead>
                    <tr>
                        <th>ID</th>
                        <th>标题</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="item in dataList">
                        <td>{{item.id}}</td>
                        <td>{{item.title}}</td>
                    </tr>
                    </tbody>
                </table>
            </div>
        `
    }

    var app = new Vue({
        el: '#app',
        data: {
            name: "linda",
        },
        components: {
            Demo,
            Bb: Bili
        },
        methods: {}
    })
</script>
</body>
</html>

# 3.2 全局组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>=======当前页面=======</h1>
    {{name}}

    <h1>=======引入子组件=======</h1>
    <Demo></Demo>
    <Demo></Demo>
    <Bili></Bili>
    <Bili></Bili>
</div>
<script>
    //创建子组件
    Vue.component('Demo', {
        data: function () {
            return {
                msg: '哈哈哈哈哈'
            }
        },
        template: `
            <div>
                <h1>{{msg}}</h1>
                <input type="text" v-model="msg"/>
                <input type="button" @click="showMeg" value="点我呀">
            </div>
        `,
        methods: {
            showMeg: function () {
                alert(this.msg);
            }
        }
    });

    //创建子组件
    Vue.component('Bili', {
        // 组件中的data是一个方法,并返回值(与Vue对象创建不同)
        data: function () {
            return {
                dataList: [
                    {"id": 1, "title": "2022再见"},
                    {"id": 2, "title": "2023你好"},
                ]
            }
        },
        template: `
            <div>
                <h1>数据列表</h1>
                <table border="1">
                    <thead>
                    <tr>
                        <th>ID</th>
                        <th>标题</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="item in dataList">
                        <td>{{item.id}}</td>
                        <td>{{item.title}}</td>
                    </tr>
                    </tbody>
                </table>
            </div>
        `
    });

    var app = new Vue({
        el: '#app',
        data: {
            name: "linda",
        },
        methods: {}
    })
</script>
</body>
</html>

# 4.vue-router组件

vue + vue-router组件 可以实现 SPA(single Page Application),即:单页面应用

单页面应用,简而言之就是项目只有一个页面。

一个页面如何呈现多种界面的效果呢?

  • 基于vue开发多个组件,例如:活动组件、课程组件、咨询组件
  • 在页面上 vue-router 用来管理这些组件,用户点击某个按钮,就显示特定的组件(数据基于Ajax获取)。

# 4.1 下载和引用

官方地址:https://router.vuejs.org/zh/

下载地址:https://unpkg.com/vue-router@3

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <!--  vue-router.js 依赖 vue.js -->
    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
    
</head>
<body>
	...
</body>
</html>

注意:后期用脚手架开发时,可以直接使用npm下载和引用。

# 4.2 快速上手

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>day03v1</title>
    <style>
        body {
            margin: 0;
        }

        .container {
            width: 980px;
            margin: 0 auto;
        }

        .menu {
            height: 48px;
            background-color: #499ef3;
            line-height: 48px;

        }

        .menu a {
            color: white;
            text-decoration: none;
            padding: 0 10px;
        }
    </style>

    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
</head>
<body>
    <div id="app">
        <div class="menu">
            <div class="container">
                <router-link to="/">Logo</router-link>
                <router-link to="/home">首页</router-link>
                <router-link to="/course">课程</router-link>
                <router-link to="/news">咨询</router-link>
            </div>
            <div class="container">
                <router-view></router-view>
            </div>
            
        </div>
    </div>
    <script>
        const Home = {template:'<div><h1>首页内容</h1></div>'}
        const Course = {template:'<div><h1>课程内容</h1></div>'}
        const News = {template:'<div><h1>咨询内容</h1></div>'}

        const router = new VueRouter({
            routes: [
                {
                    path: "/",
                    component: Home,
                },
                {
                    path: "/home",
                    component: Home,
                },
                {
                    path: "/course",
                    component: Course,
                },
                {
                    path: "/news",
                    component: News,
                }
            ]
        })

        var app = new Vue({
            el: "#app",
            data:{
            },
            router,   
        });
    </script>
</body>
</html>

# 案例:开发学城(第1版)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>开发学城</title>
    <style>
        body {
            margin: 0;
        }

        .container {
            width: 1100px;
            margin: 0 auto;
        }

        .menu {
            height: 48px;
            background-color: #499ef3;
            line-height: 48px;

        }

        .menu a {
            color: white;
            text-decoration: none;
            padding: 0 10px;
        }

        .course-list {
            display: flex;
            flex-wrap: wrap;
            justify-content: flex-start;
        }

        .course-list .item {
            width: 248px;
            padding: 10px;
            border: 1px solid #dddddd;
            margin-right: 5px;
            margin-top: 10px;
        }

        .course-list .item img {
            width: 100%;
            height: 120px;
        }
    </style>

    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
</head>
<body>
    <div id="app">
        <div class="menu">
            <div class="container">
                <router-link to="/">开发学城</router-link>
                <router-link to="/home">首页</router-link>
                <router-link to="/course">课程</router-link>
                <router-link to="/news">咨询</router-link>
            </div> 
        </div>
        <div class="container">
            <router-view></router-view>
        </div>

    </div>
    <script>
        const Home = {
        data: function () {
            return {
                title: "欢迎使用开发学城"
            }
        },
        template: `<h2>{{title}}</h2>`
        }

        const Course = {
            data: function(){
                return {
                    courseList: []
                }
            },
            created: function(){
                /* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面相关的DOM创建并显示在页面上】
                 - 可以去操作组件对象,例如:this.courseList = [11,22,33]
                 - 不可以去操作DOM,例如:document.getElementById (未创建)

                实际会用 axios({请求数据})
                */
               this.courseList = [
                {"name": "Golang从入门到精通", "cover": "http://127.0.0.1:5500/src/img/go.png"},
                {"name": "Python从入门到精通", "cover": "http://127.0.0.1:5500/src/img/py.png"},
                {"name": "DBA进阶之旅之MySQL", "cover": "http://127.0.0.1:5500/src/img/mysql.png"},
                {"name": "DBA进阶之旅之Redis", "cover": "http://127.0.0.1:5500/src/img/redis.png"},
               ]

            },
            mounted: function () {
            /* DOM对象已在页面上生成,此时就可以 */
            },
            template: `
                <div class="course-list">
                <div class="item" v-for="item in courseList">
                    <img :src="item.cover" alt="">
                    <a>{{item.name}}</a>
                </div>
                </div>
            `
        }
        const News = {template:'<div><h2>咨询内容</h2></div>'}

        const router = new VueRouter({
            routes: [
                {
                    path: "/",
                    component: Home,
                },
                {
                    path: "/home",
                    component: Home,
                },
                {
                    path: "/course",
                    component: Course,
                },
                {
                    path: "/news",
                    component: News,
                }
            ]
        })

        var app = new Vue({
            el: "#app",
            data:{
            },
            router,   
        });
    </script>
</body>
</html>

# 4.3 路由和传值

当某个组件可以根据某些参数值的不同,展示不同效果时,需要用到动态路由。

例如:访问网站看到课程列表,点击某个课程,就可以跳转到课程详细页面(根据课程ID不同展示不同数据)。

如何来设置动态路由呢?

  • 定义路由

    const router = new VueRouter({
        routes: [
            { path: '/', component: Home},
            { path: '/course', component: Course, name: "Course"}
            { path: '/detail/:id', component: Detail, name: "Detail"}
        ],
    })
    
  • HTML展示

    <div>
        <router-link to="/">首页</router-link>
        <router-link to="/course">课程</router-link>
        <router-link to="/detail/123">课程</router-link>
        
        <router-link :to="{path:'/course'}">课程</router-link>
        <router-link :to="{path:'/course?size=19&page=2'}">课程</router-link>
        <router-link :to="{path:'/course', query:{size:19,page:2}">课程</router-link>
        
        <router-link :to="{name:'Course'}">课程</router-link>
        <router-link :to="{name:'Course', query:{size:19,page:2} }">课程</router-link>
    
        <router-link :to="{path:'/detail/22',query:{size:123}}">Linux</router-link>
        <router-link :to="{name:'Detail',params:{id:3}, query:{size:29}}">网络安全</router-link>
    </div>
    
    <h1>内容区域</h1>
    <router-view></router-view>
    
  • 组件获取URL传值和GET参数

     const Detail = {
         data: function () {
             return {
                 title: "详细页面",
                 paramDict: null,
                 queryDict: null,
    
             }
         },
         created: function () {
             this.paramDict = this.$route.params;
             this.queryDict = this.$route.query;
             // 发送axios请求
         },
         template: `<div><h2>{{title}}</h2><div>当前请求的数据 {{paramDict}}  {{queryDict}}</div></div>`
     }
    

# 案例:开发学城(第2版)

点击课程,查看课程详细页面。

image-20220124194542661

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>开发学城02</title>
    <style>
        body {
            margin: 0;
        }

        .container {
            width: 1100px;
            margin: 0 auto;
        }

        .menu {
            height: 48px;
            background-color: #499ef3;
            line-height: 48px;

        }

        .menu a {
            color: white;
            text-decoration: none;
            padding: 0 10px;
        }

        .course-list {
            display: flex;
            flex-wrap: wrap;
            justify-content: flex-start;
        }

        .course-list .item {
            width: 248px;
            padding: 10px;
            border: 1px solid #dddddd;
            margin-right: 5px;
            margin-top: 10px;
        }

        .course-list .item img {
            width: 100%;
            height: 120px;
        }
    </style>

    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
</head>
<body>
    <div id="app">
        <div class="menu">
            <div class="container">
                <router-link to="/">开发学城</router-link>
                <router-link to="/home">首页</router-link>
                <router-link to="/course">课程</router-link>
                <router-link to="/news">咨询</router-link>
            </div> 
        </div>

        <div class="container">
            <router-view></router-view>
        </div>

    </div>
    <script>
        const Home = {
        data: function () {
            return {
                title: "欢迎使用开发学城"
            }
        },
        template: `<h2>{{title}}</h2>`
        }

        const Course = {
            data: function(){
                return {
                    courseList: []
                }
            },
            created: function(){
                /* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面相关的DOM创建并显示在页面上】
                 - 可以去操作组件对象,例如:this.courseList = [11,22,33]
                 - 不可以去操作DOM,例如:document.getElementById (未创建)

                实际会用 axios({请求数据})
                */
               this.courseList = [
                {id: 111, name: "Golang从入门到精通", cover: "http://127.0.0.1:5500/src/img/go.png"},
                {id: 222, name: "Python从入门到精通", cover: "http://127.0.0.1:5500/src/img/py.png"},
                {id: 333, name: "DBA进阶之旅之MySQL", cover: "http://127.0.0.1:5500/src/img/mysql.png"},
                {id: 444, name: "DBA进阶之旅之Redis", cover: "http://127.0.0.1:5500/src/img/redis.png"},
               ]

            },
            mounted: function () {
            /* DOM对象已在页面上生成,此时就可以 */
            },
            template: `
                <div class="course-list">
                    <div class="item" v-for="item in courseList">
                        <router-link :to="{name: 'Detail', params: {id: item.id}}">
                            <img :src="item.cover" alt="">
                        </router-link>
                        <a>{{item.name}}</a>
                    </div>
                </div>
            `
        }

        const Detail = {
            // data: function(){
            //     return {
            //         title: "详细页面",
            //         paramDict: null,
            //         queryDict: null,
            //     }
            // },
            // created: function () {
            //     this.paramDict = this.$route.params;
            //     this.queryDict = this.$route.query;
            //     // 发送axios请求
            // },

            data: function(){
                return {
                    title: "详细页面",
                    courseId: null
                }
            },
            created: function () {
                this.courseId = this.$route.params.id;
                // 此处可以根据课程ID,发送ajax请求获取课程详细信息
        },
            template: `<div><h2>课程详细页面</h2><div>当前课程ID为:{{courseId}}</div></div>`
        }

        const News = {template:'<div><h2>咨询内容</h2></div>'}

        const router = new VueRouter({
            routes: [
                {
                    path: "/",
                    component: Home,
                },
                {
                    path: "/home",
                    component: Home,
                },
                {
                    path: "/course",
                    component: Course,
                    name: "Course",
                },
                {
                    path: "/detail/:id",
                    component: Detail,
                    name: "Detail",
                },
                {
                    path: "/news",
                    component: News,
                }
            ]
        })

        var app = new Vue({
            el: "#app",
            data:{
            },
            router,   
        });
    </script>
</body>
</html>

# 4.5 无法刷新

上述编写案例是没有问题,但如果在开发中会涉及到 同一个路由的跳转(默认不会重新加载页面,数据无法获取)。

例如:在详细页面再出现一个课程推荐,即:在课程详细,点击推荐的课程后跳转到课程详细页面(课程ID不同),此时课程的ID还是原来加载的ID,无法获取推荐课程的ID。

如何解决呢?

在课程详细的组件中设置watch属性即可,watch会监测$route 值,一旦发生变化,就执行相应的函数。

const Detail = {
    data: function () {
        return {
            title: "详细页面",
            courseId: null,

        }
    },
    created: function () {
        this.courseId = this.$route.params.id;
        this.getCourseDetail();
    },
    watch: {
        $route:function(to, from) {
            this.courseId = to.params.id;
            // this.getCourseDetail();
        }
    },
    methods: {
        getCourseDetail: function () {
            // 根据this.courseId获取课程详细信息
        }
    },
    template: `<div><h2>{{title}}</h2><div>当前请求的数据 {{paramDict}}  {{queryDict}}</div></div>`
}

# 案例:开发学城(第3版)

在详细页面实现推荐课程

image-20220124200154347

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>开发学城03</title>
    <style>
        body {
            margin: 0;
        }

        .container {
            width: 1100px;
            margin: 0 auto;
        }

        .menu {
            height: 48px;
            background-color: #499ef3;
            line-height: 48px;

        }

        .menu a {
            color: white;
            text-decoration: none;
            padding: 0 10px;
        }

        .course-list {
            display: flex;
            flex-wrap: wrap;
            justify-content: flex-start;
        }

        .course-list .item {
            width: 248px;
            padding: 10px;
            border: 1px solid #dddddd;
            margin-right: 5px;
            margin-top: 10px;
        }

        .course-list .item img {
            width: 100%;
            height: 120px;
        }
    </style>

    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
</head>
<body>
    <div id="app">
        <div class="menu">
            <div class="container">
                <router-link to="/">开发学城</router-link>
                <router-link to="/home">首页</router-link>
                <router-link to="/course">课程</router-link>
                <router-link to="/news">咨询</router-link>
            </div> 
        </div>

        <div class="container">
            <router-view></router-view>
        </div>

    </div>
    <script>
        const Home = {
        data: function () {
            return {
                title: "欢迎使用开发学城"
            }
        },
        template: `<h2>{{title}}</h2>`
        }

        const Course = {
            data: function(){
                return {
                    courseList: []
                }
            },
            created: function(){
                /* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面相关的DOM创建并显示在页面上】
                 - 可以去操作组件对象,例如:this.courseList = [11,22,33]
                 - 不可以去操作DOM,例如:document.getElementById (未创建)

                实际会用 axios({请求数据})
                */
               this.courseList = [
                {id: 111, name: "Golang从入门到精通", cover: "http://127.0.0.1:5500/src/img/go.png"},
                {id: 222, name: "Python从入门到精通", cover: "http://127.0.0.1:5500/src/img/py.png"},
                {id: 333, name: "DBA进阶之旅之MySQL", cover: "http://127.0.0.1:5500/src/img/mysql.png"},
                {id: 444, name: "DBA进阶之旅之Redis", cover: "http://127.0.0.1:5500/src/img/redis.png"},
               ]

            },
            mounted: function () {
            /* DOM对象已在页面上生成,此时就可以 */
            },
            template: `
                <div class="course-list">
                    <div class="item" v-for="item in courseList">
                        <router-link :to="{name: 'Detail', params: {id: item.id}}">
                            <img :src="item.cover" alt="">
                        </router-link>
                        <a>{{item.name}}</a>
                    </div>
                </div>
            `
        }

        const Detail = {
            // data: function(){
            //     return {
            //         title: "详细页面",
            //         paramDict: null,
            //         queryDict: null,
            //     }
            // },
            // created: function () {
            //     this.paramDict = this.$route.params;
            //     this.queryDict = this.$route.query;
            //     // 发送axios请求
            // },

            data: function(){
                return {
                    title: "详细页面",
                    courseId: null,
                    hotCourseList: [
                    {id: 333, title: "DBA进阶之旅之MySQL"},
                    {id: 444, title: "DBA进阶之旅之Redis"},
                ],
                }
            },
            created: function () {
                this.courseId = this.$route.params.id;
                // 此处可以根据课程ID,发送ajax请求获取课程详细信息
                this.getCourseDetail();
            },
            watch: {
                $route:function(to, from) {
                    this.courseId = to.params.id;
                    // this.getCourseDetail();
                }
            },

            methods: {
                getCourseDetail: function () {
                // 根据this.courseId获取课程详细信息

                }
            },

            template:`
                <div>
                    <h2>课程详细页面</h2>
                    <div>当前课程ID为:{{courseId}}</div>
                    <h3>课程推荐</h3>
                    <ul>
                        <li v-for="item in hotCourseList">
                            <router-link :to="{name:'Detail', params:{id:item.id}}">{{item.title}}</router-link>
                        </li>
                    </ul>
                </div>`
        }

        const News = {template:'<div><h2>咨询内容</h2></div>'}

        const router = new VueRouter({
            routes: [
                {
                    path: "/",
                    component: Home,
                },
                {
                    path: "/home",
                    component: Home,
                },
                {
                    path: "/course",
                    component: Course,
                    name: "Course",
                },
                {
                    path: "/detail/:id",
                    component: Detail,
                    name: "Detail",
                },
                {
                    path: "/news",
                    component: News,
                }
            ]
        })

        var app = new Vue({
            el: "#app",
            data:{
            },
            router,   
        });
    </script>
</body>
</html>

# 4.6 路由嵌套

const router = new VueRouter({
  routes: [
    {
      path: '/pins/',
      component: Pins,
      children: [
        {
          // 当 /pins/hot 匹配成功,
          // Hot组件 会被渲染在 Pins 的 <router-view> 中
          path: 'hot',
          component: Hot
        },
        {
          // 当 /pins/following 匹配成功,
          // Following组件 会被渲染在 Pins 的 <router-view> 中
          path: 'following',
          component: Following
        }
      ]
    }
  ]
})

# 案例:开发学城(第4版)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>开发学城04</title>
    <style>
        body {
            margin: 0;
        }

        .container {
            width: 1100px;
            margin: 0 auto;
        }

        .menu {
            height: 48px;
            background-color: #499ef3;
            line-height: 48px;

        }

        .menu a {
            color: white;
            text-decoration: none;
            padding: 0 10px;
        }

        .course-list {
            display: flex;
            flex-wrap: wrap;
            justify-content: flex-start;
        }

        .course-list .item {
            width: 248px;
            padding: 10px;
            border: 1px solid #dddddd;
            margin-right: 5px;
            margin-top: 10px;
        }

        .course-list .item img {
            width: 100%;
            height: 120px;
        }
    </style>

    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
</head>
<body>
    <div id="app">
        <div class="menu">
            <div class="container">
                <router-link to="/">开发学城</router-link>
                <router-link to="/pins">沸点</router-link>
                <router-link to="/home">首页</router-link>
                <router-link to="/course">课程</router-link>
                <router-link to="/news">咨询</router-link>
            </div> 
        </div>

        <div class="container">
            <router-view></router-view>
        </div>

    </div>
    <script>
        const Home = {
        data: function () {
            return {
                title: "欢迎使用开发学城"
            }
        },
        template: `<h2>{{title}}</h2>`
        }

        const Course = {
            data: function(){
                return {
                    courseList: []
                }
            },
            created: function(){
                /* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面相关的DOM创建并显示在页面上】
                 - 可以去操作组件对象,例如:this.courseList = [11,22,33]
                 - 不可以去操作DOM,例如:document.getElementById (未创建)

                实际会用 axios({请求数据})
                */
               this.courseList = [
                {id: 111, name: "Golang从入门到精通", cover: "http://127.0.0.1:5500/src/img/go.png"},
                {id: 222, name: "Python从入门到精通", cover: "http://127.0.0.1:5500/src/img/py.png"},
                {id: 333, name: "DBA进阶之旅之MySQL", cover: "http://127.0.0.1:5500/src/img/mysql.png"},
                {id: 444, name: "DBA进阶之旅之Redis", cover: "http://127.0.0.1:5500/src/img/redis.png"},
               ]

            },
            mounted: function () {
            /* DOM对象已在页面上生成,此时就可以 */
            },
            template: `
                <div class="course-list">
                    <div class="item" v-for="item in courseList">
                        <router-link :to="{name: 'Detail', params: {id: item.id}}">
                            <img :src="item.cover" alt="">
                        </router-link>
                        <a>{{item.name}}</a>
                    </div>
                </div>
            `
        }

        const Detail = {
            // data: function(){
            //     return {
            //         title: "详细页面",
            //         paramDict: null,
            //         queryDict: null,
            //     }
            // },
            // created: function () {
            //     this.paramDict = this.$route.params;
            //     this.queryDict = this.$route.query;
            //     // 发送axios请求
            // },

            data: function(){
                return {
                    title: "详细页面",
                    courseId: null,
                    hotCourseList: [
                    {id: 333, title: "DBA进阶之旅之MySQL"},
                    {id: 444, title: "DBA进阶之旅之Redis"},
                ],
                }
            },
            created: function () {
                this.courseId = this.$route.params.id;
                // 此处可以根据课程ID,发送ajax请求获取课程详细信息
                this.getCourseDetail();
            },
            watch: {
                $route:function(to, from) {
                    this.courseId = to.params.id;
                    // this.getCourseDetail();
                }
            },

            methods: {
                getCourseDetail: function () {
                // 根据this.courseId获取课程详细信息

                }
            },

            template:`
                <div>
                    <h2>课程详细页面</h2>
                    <div>当前课程ID为:{{courseId}}</div>
                    <h3>课程推荐</h3>
                    <ul>
                        <li v-for="item in hotCourseList">
                            <router-link :to="{name:'Detail', params:{id:item.id}}">{{item.title}}</router-link>
                        </li>
                    </ul>
                </div>`
        }

        const News = {template:'<div><h2>咨询内容</h2></div>'}

        const Pins = {
            data: function(){
                return {}
            },
            template: `
            <div>
                <h2>沸点专区</h2>
                <router-link :to="{name:'Hot'}">热点</router-link>
                <router-link :to="{name:'Following'}">关注</router-link>
                <router-view></router-view>
            </div>
            `
        }

        const Hot = {template: `<div><h2>Hot页面</h2></div>`}
        const Following = {template: `<div><h2>Following页面</h2></div>`}

        const router = new VueRouter({
            routes: [
                {
                    path: "/",
                    component: Home,
                },
                {
                    path: "/pins",
                    component: Pins,
                    name: 'Pins',
                    children:[
                        {
                            // 当 /pins/hot 匹配成功,
                            // Hot组件 会被渲染在 Pins 的 <router-view> 中
                            path: 'hot',
                            component: Hot,
                            name:'Hot'
                        },
                        {
                            // 当 /pins/following 匹配成功,
                            // Following组件 会被渲染在 Pins 的 <router-view> 中
                            path: 'following',
                            component: Following,
                            name:'Following'
                        }
                    ]
                },
                {
                    path: "/home",
                    component: Home,
                },
                {
                    path: "/course",
                    component: Course,
                    name: "Course",
                },
                {
                    path: "/detail/:id",
                    component: Detail,
                    name: "Detail",
                },
                {
                    path: "/news",
                    component: News,
                }
            ]
        })

        var app = new Vue({
            el: "#app",
            data:{
            },
            router,   
        });
    </script>
</body>
</html>

# 案例:后台分类菜单

image-20220124222144176

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body {
            margin: 0;
        }

        .header {
            height: 48px;
            background-color: #499ef3;
            line-height: 48px;

        }

        .header a {
            color: white;
            text-decoration: none;
            padding: 0 10px;
        }

        .body .left-menu {
            width: 180px;
            border: 1px solid #dddddd;
            border-bottom: 0;
            position: absolute;
            left: 1px;
            top: 50px;
            bottom: 0;
            overflow: auto;
            background-color: #f3f5f7;
        }

        .body .left-menu .head {
            border-bottom: 1px solid #dddddd;
            text-align: center;
            font-size: 18px;
            font-weight: bold;
            padding: 15px;
        }

        .body .left-menu a {
            display: block;
            padding: 10px;
            border-bottom: 1px solid #dddddd;
        }

        .body .right-body {
            position: absolute;
            left: 183px;
            top: 50px;
            right: 0;
            bottom: 0;
            overflow: auto;
            padding: 10px;

        }
    </style>

    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
    <script src="axios.min.js"></script>
</head>
<body>
<div id="app">
    <div class="header">
        <router-link to="/">Logo</router-link>
        <router-link to="/home">首页</router-link>
        <router-link to="/task">任务宝</router-link>
        <router-link to="/message">消息宝</router-link>
    </div>
    <div class="body">
        <router-view></router-view>
    </div>

</div>

<script>

    const Home = {
        data: function () {
            return {
                title: "欢迎使用xx系统"
            }
        },
        template: `<h2>{{title}}</h2>`
    };

    const Task = {
        data: function () {
            return {}
        },
        template: `
            <div>
                <div class="left-menu">
                    <div class="head">任务宝</div>
                    <router-link :to="{name:'Fans'}">粉丝</router-link>
                    <router-link :to="{name:'Spread'}">推广码</router-link>
                    <router-link :to="{name:'Statistics'}">数据统计</router-link>
                </div>
                <div class="right-body">
                    <router-view></router-view>
                </div>

            </div>`
    };

    const Fans = {template: `<h3>粉丝页面</h3>`};
    const Spread = {template: `<h3>推广码页面</h3>`};
    const Statistics = {template: `<h3>数据统计页面</h3>`};

    const Message = {
        data: function () {
            return {}
        },
        template: `
            <div>
                <div class="left-menu">
                    <div class="head">消息宝</div>
                    <router-link :to="{name:'Sop'}">SOP</router-link>
                    <router-link :to="{name:'Send'}">推送管理</router-link>
                </div>
                <div class="right-body">
                    <router-view></router-view>
                </div>

            </div>`
    };

    const Sop = {template: `<h3>SOP页面</h3>`};
    const Send = {template: `<h3>推送管理页面</h3>`};

    const router = new VueRouter({
        routes: [
            {path: '/', component: Home},
            {path: '/home', component: Home},
            {
                path: '/task',
                component: Task,
                name: 'Task',
                children: [
                    {
                        path: '',
                        // component: Fans,
                        // redirect:'/task/fans'
                        redirect: {name: 'Fans'}
                    },
                    {
                        path: 'fans',
                        component: Fans,
                        name: 'Fans'
                    },
                    {
                        path: 'spread',
                        component: Spread,
                        name: 'Spread'
                    },
                    {
                        path: 'statistics',
                        component: Statistics,
                        name: 'Statistics'
                    }
                ]
            },
            {
                path: '/message',
                component: Message,
                name: 'Message',
                children: [
                    {
                        path: 'sop',
                        component: Sop,
                        name: 'Sop'
                    },
                    {
                        path: 'send',
                        component: Send,
                        name: 'Send'
                    }
                ]
            }
        ]
    })

    var app = new Vue({
        el: '#app',
        data: {},
        methods: {},
        router: router
    })
</script>
</body>
</html>

# 4.7 编程式导航

除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。

想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

  • router.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.replace

    // 字符串
    router.replace('home')
    
    // 对象
    router.replace({ path: 'home' })
    
    // 命名的路由
    router.replace({ name: 'user', params: { userId: '123' }})
    
    // 带查询参数,变成 /register?plan=private
    router.replace({ path: 'register', query: { plan: 'private' }})
    
    # 跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。
    
  • router.go 这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步

    // 在浏览器记录中前进一步,等同于 history.forward()
    router.go(1)
    
    // 后退一步记录,等同于 history.back()
    router.go(-1)
    
    // 前进 3 步记录
    router.go(3)
    
    // 如果 history 记录不够用,那就默默地失败呗
    router.go(-100)
    router.go(100)
    

# 案例:登录跳转(含顶部)

image-20220124230751442

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body {
            margin: 0;
        }

        .header {
            height: 48px;
            background-color: #499ef3;
            line-height: 48px;

        }

        .header a {
            color: white;
            text-decoration: none;
            padding: 0 10px;
        }


    </style>
    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
</head>
<body>
<div id="app">
    <div class="header">
        <router-link to="/">Logo</router-link>
        <router-link to="/home">首页</router-link>
        <router-link to="/task">任务宝</router-link>
        <router-link to="/message">消息宝</router-link>

        <div style="float: right;">
            <router-link to="/login">登录</router-link>
        </div>
    </div>
    <div class="body">
        <router-view></router-view>
    </div>

</div>

<script>

    const Home = {
        data: function () {
            return {
                title: "欢迎使用xx系统"
            }
        },
        template: `<h2>{{title}}</h2>`
    };

    const Task = {
        data: function () {
            return {}
        },
        template: `
            <div>
                <h2>任务宝页面</h2>
            </div>`
    };

    const Message = {
        data: function () {
            return {}
        },
        template: `
            <div>
                <h2>消息宝页面</h2>
            </div>`
    };

    const Login = {
        data: function () {
            return {
                user: '',
                pwd: ''
            }
        },
        methods: {
            doLogin: function () {
                if (this.user.length > 0 && this.pwd.length > 0) {
                    this.$router.push({name: 'Task'});
                    // this.$router.replace({name: 'Task'});
                }
            }
        },
        template: `
            <div style="width: 500px;margin: 100px auto">
                <input type="text" placeholder="用户名" v-model="user"/>
                <input type="text" placeholder="密码" v-model="pwd" />
                <input type="button" value="提 交"  @click="doLogin" />
            </div>
         `
    };
    const router = new VueRouter({
        routes: [
            {path: '/', component: Home},
            {path: '/home', component: Home},
            {path: '/login', component: Login, name: 'Login'},
            {path: '/task', component: Task, name: 'Task'},
            {path: '/message', component: Message, name: 'Message'}
        ]
    })

    var app = new Vue({
        el: '#app',
        data: {},
        methods: {},
        router: router
    })
</script>
</body>
</html>

# 案例:登录跳转(不含顶部)

image-20220124230751442

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body {
            margin: 0;
        }

        .header {
            height: 48px;
            background-color: #499ef3;
            line-height: 48px;

        }

        .header a {
            color: white;
            text-decoration: none;
            padding: 0 10px;
        }

        .body .left-menu {
            width: 180px;
            border: 1px solid #dddddd;
            border-bottom: 0;
            position: absolute;
            left: 1px;
            top: 50px;
            bottom: 0;
            overflow: auto;
            background-color: #f3f5f7;
        }

        .body .left-menu .head {
            border-bottom: 1px solid #dddddd;
            text-align: center;
            font-size: 18px;
            font-weight: bold;
            padding: 15px;
        }

        .body .left-menu a {
            display: block;
            padding: 10px;
            border-bottom: 1px solid #dddddd;
        }

        .body .right-body {
            position: absolute;
            left: 183px;
            top: 50px;
            right: 0;
            bottom: 0;
            overflow: auto;
            padding: 10px;

        }
    </style>
    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
</head>
<body>
<div id="app">
    <router-view></router-view>
</div>

<script>

    const Home = {
        data: function () {
            return {
                title: "欢迎使用xx系统"
            }
        },
        template: `
            <div>
                <div class="header">
                    <router-link to="/">Logo</router-link>
                    <router-link to="/home">首页</router-link>
                    <router-link :to="{name:'Task'}">任务宝</router-link>
                    <router-link :to="{name:'Message'}">消息宝</router-link>

                    <div style="float: right;">
                        <router-link to="/login">登录</router-link>
                    </div>
                </div>
                <div class="body">
                    <router-view></router-view>
                </div>

            </div>
        `
    };

    const Index = {template: '<h3>这是个首页呀...</h3>'}

    const Task = {
        data: function () {
            return {}
        },
        template: `
            <div>
                <div class="left-menu">
                    <div class="head">任务宝</div>
                    <router-link :to="{name:'Fans'}">粉丝</router-link>
                    <router-link :to="{name:'Spread'}">推广码</router-link>
                    <router-link :to="{name:'Statistics'}">数据统计</router-link>
                </div>
                <div class="right-body">
                    <router-view></router-view>
                </div>

            </div>`
    };

    const Fans = {template: `<h3>粉丝页面</h3>`};
    const Spread = {template: `<h3>推广码页面</h3>`};
    const Statistics = {template: `<h3>数据统计页面</h3>`};

    const Message = {
        data: function () {
            return {}
        },
        template: `
            <div>
                <div class="left-menu">
                    <div class="head">消息宝</div>
                    <router-link :to="{name:'Sop'}">SOP</router-link>
                    <router-link :to="{name:'Send'}">推送管理</router-link>
                </div>
                <div class="right-body">
                    <router-view></router-view>
                </div>

            </div>`
    };

    const Sop = {template: `<h3>SOP页面</h3>`};
    const Send = {template: `<h3>推送管理页面</h3>`};
    const Login = {
        data: function () {
            return {
                user: '',
                pwd: ''
            }
        },
        methods: {
            doLogin: function () {
                if (this.user.length > 0 && this.pwd.length > 0) {
                    this.$router.push({name: 'Index'});
                    // this.$router.replace({name: 'Task'});
                }
            }
        },
        template: `
            <div style="width: 500px;margin: 100px auto">
                <input type="text" placeholder="用户名" v-model="user"/>
                <input type="text" placeholder="密码" v-model="pwd" />
                <input type="button" value="提 交"  @click="doLogin" />
            </div>
         `
    };



    const router = new VueRouter({
        routes: [
            {
                path: '/',
                // component: Home,
                redirect: '/login'
            },
            {path: '/login', component: Login, name: 'Login'},
            {
                path: '/home',
                component: Home,
                children: [
                    {
                        path: '',
                        component: Index,
                        name: "Index"
                    },
                    {
                        path: 'task',
                        component: Task,
                        name: 'Task',
                        children: [
                            {
                                path: 'fans',
                                component: Fans,
                                name: 'Fans'
                            },
                            {
                                path: 'spread',
                                component: Spread,
                                name: 'Spread'
                            },
                            {
                                path: 'statistics',
                                component: Statistics,
                                name: 'Statistics'
                            }
                        ]
                    },
                    {
                        path: 'message',
                        component: Message,
                        name: 'Message',
                        children: [
                            {
                                path: 'sop',
                                component: Sop,
                                name: 'Sop'
                            },
                            {
                                path: 'send',
                                component: Send,
                                name: 'Send'
                            }
                        ]
                    }
                ],
            },

        ]
    })

    var app = new Vue({
        el: '#app',
        data: {},
        methods: {},
        router: router
    })
</script>
</body>
</html>

# 4.8 导航守卫

在基于vue-router实现访问跳转时,都会执行一个钩子。

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
	// to: Route: 即将要进入的目标 路由对象
	// from: Route: 当前导航正要离开的路由
    // next() 继续向后执行
    // next(false) 中断导航,保持当前所在的页面。
    // next('/')   next({path:'/'}) next({name:'Login'})  跳转到指定页面
})

注意:可以基于他实现未登录跳转登录页面。

# 案例:登录拦截(全局)

未登录时,访问后台管理页面,自动跳转到登录页面。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body {
            margin: 0;
        }

        .header {
            height: 48px;
            background-color: #499ef3;
            line-height: 48px;

        }

        .header a {
            color: white;
            text-decoration: none;
            padding: 0 10px;
        }

        .body .left-menu {
            width: 180px;
            border: 1px solid #dddddd;
            border-bottom: 0;
            position: absolute;
            left: 1px;
            top: 50px;
            bottom: 0;
            overflow: auto;
            background-color: #f3f5f7;
        }

        .body .left-menu .head {
            border-bottom: 1px solid #dddddd;
            text-align: center;
            font-size: 18px;
            font-weight: bold;
            padding: 15px;
        }

        .body .left-menu a {
            display: block;
            padding: 10px;
            border-bottom: 1px solid #dddddd;
        }

        .body .right-body {
            position: absolute;
            left: 183px;
            top: 50px;
            right: 0;
            bottom: 0;
            overflow: auto;
            padding: 10px;

        }
    </style>
    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
</head>
<body>
<div id="app">
    <router-view></router-view>
</div>

<script>

    const Home = {
        data: function () {
            return {
                title: "欢迎使用xx系统"
            }
        },
        methods: {
            doLogout: function () {
                sessionStorage.clear();
                this.$router.push({name: "Login"});
            }
        },
        template: `
            <div>
                <div class="header">
                    <router-link to="/">Logo</router-link>
                    <router-link to="/home">首页</router-link>
                    <router-link :to="{name:'Task'}">任务宝</router-link>
                    <router-link :to="{name:'Message'}">消息宝</router-link>

                    <div style="float: right;">
                        <a @click="doLogout">注销</a>
                    </div>
                </div>
                <div class="body">
                    <router-view></router-view>
                </div>

            </div>
        `
    };

    const Index = {template: '<h3>这是个首页呀...</h3>'}

    const Task = {
        data: function () {
            return {}
        },
        template: `
            <div>
                <div class="left-menu">
                    <div class="head">任务宝</div>
                    <router-link :to="{name:'Fans'}">粉丝</router-link>
                    <router-link :to="{name:'Spread'}">推广码</router-link>
                    <router-link :to="{name:'Statistics'}">数据统计</router-link>
                </div>
                <div class="right-body">
                    <router-view></router-view>
                </div>

            </div>`
    };

    const Fans = {template: `<h3>粉丝页面</h3>`};
    const Spread = {template: `<h3>推广码页面</h3>`};
    const Statistics = {template: `<h3>数据统计页面</h3>`};

    const Message = {
        data: function () {
            return {}
        },
        template: `
            <div>
                <div class="left-menu">
                    <div class="head">消息宝</div>
                    <router-link :to="{name:'Sop'}">SOP</router-link>
                    <router-link :to="{name:'Send'}">推送管理</router-link>
                </div>
                <div class="right-body">
                    <router-view></router-view>
                </div>

            </div>`
    };

    const Sop = {template: `<h3>SOP页面</h3>`};
    const Send = {template: `<h3>推送管理页面</h3>`};
    const Login = {
        data: function () {
            return {
                user: '',
                pwd: ''
            }
        },
        methods: {
            doLogin: function () {
                if (this.user.length > 0 && this.pwd.length > 0) {
                    sessionStorage.setItem("isLogin", true);
                    this.$router.push({name: 'Index'});
                }
            }
        },
        template: `
            <div style="width: 500px;margin: 100px auto">
                <input type="text" placeholder="用户名" v-model="user"/>
                <input type="text" placeholder="密码" v-model="pwd" />
                <input type="button" value="提 交"  @click="doLogin" />
            </div>
         `
    };
    const router = new VueRouter({
        routes: [
            {
                path: '/',
                component: Home,
                redirect: '/home'
            },
            {
                path: '/home',
                component: Home,
                name: "Home",
                children: [
                    {
                        path: '',
                        component: Index,
                        name: "Index"
                    },
                    {
                        path: 'task',
                        component: Task,
                        name: 'Task',
                        children: [
                            {
                                path: 'fans',
                                component: Fans,
                                name: 'Fans'
                            },
                            {
                                path: 'spread',
                                component: Spread,
                                name: 'Spread'
                            },
                            {
                                path: 'statistics',
                                component: Statistics,
                                name: 'Statistics'
                            }
                        ]
                    },
                    {
                        path: 'message',
                        component: Message,
                        name: 'Message',
                        children: [
                            {
                                path: 'sop',
                                component: Sop,
                                name: 'Sop'
                            },
                            {
                                path: 'send',
                                component: Send,
                                name: 'Send'
                            }
                        ]
                    }
                ],
            },
            {path: '/login', component: Login, name: 'Login'},
        ]
    })

    router.beforeEach((to, from, next) => {
        // 如果已登录,则可以继续访问目标地址
        if (sessionStorage.getItem('isLogin')) {
            next();
            return;
        }
        // 未登录,访问登录页面
        if (to.name === "Login") {
            next();
            return;
        }
        // 未登录,跳转登录页面
        // next(false); 保持当前所在页面,不跳转
        next({name: 'Login'});
    })

    var app = new Vue({
        el: '#app',
        data: {},
        methods: {},
        router: router
    })
</script>
</body>
</html>

# 案例:登录拦截(路由)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body {
            margin: 0;
        }

        .header {
            height: 48px;
            background-color: #499ef3;
            line-height: 48px;

        }

        .header a {
            color: white;
            text-decoration: none;
            padding: 0 10px;
        }

        .body .left-menu {
            width: 180px;
            border: 1px solid #dddddd;
            border-bottom: 0;
            position: absolute;
            left: 1px;
            top: 50px;
            bottom: 0;
            overflow: auto;
            background-color: #f3f5f7;
        }

        .body .left-menu .head {
            border-bottom: 1px solid #dddddd;
            text-align: center;
            font-size: 18px;
            font-weight: bold;
            padding: 15px;
        }

        .body .left-menu a {
            display: block;
            padding: 10px;
            border-bottom: 1px solid #dddddd;
        }

        .body .right-body {
            position: absolute;
            left: 183px;
            top: 50px;
            right: 0;
            bottom: 0;
            overflow: auto;
            padding: 10px;

        }
    </style>
    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
</head>
<body>
<div id="app">
    <router-view></router-view>
</div>

<script>

    const Home = {
        data: function () {
            return {
                title: "欢迎使用xx系统"
            }
        },
        methods: {
            doLogout: function () {
                sessionStorage.clear();
                this.$router.push({name: "Login"});
            }
        },
        template: `
            <div>
                <div class="header">
                    <router-link to="/">Logo</router-link>
                    <router-link to="/home">首页</router-link>
                    <router-link :to="{name:'Task'}">任务宝</router-link>
                    <router-link :to="{name:'Message'}">消息宝</router-link>

                    <div style="float: right;">
                        <a @click="doLogout">注销</a>
                    </div>
                </div>
                <div class="body">
                    <router-view></router-view>
                </div>

            </div>
        `
    };

    const Index = {template: '<h3>这是个首页呀...</h3>'}

    const Task = {
        data: function () {
            return {}
        },
        template: `
            <div>
                <div class="left-menu">
                    <div class="head">任务宝</div>
                    <router-link :to="{name:'Fans'}">粉丝</router-link>
                    <router-link :to="{name:'Spread'}">推广码</router-link>
                    <router-link :to="{name:'Statistics'}">数据统计</router-link>
                </div>
                <div class="right-body">
                    <router-view></router-view>
                </div>

            </div>`
    };

    const Fans = {template: `<h3>粉丝页面</h3>`};
    const Spread = {template: `<h3>推广码页面</h3>`};
    const Statistics = {template: `<h3>数据统计页面</h3>`};

    const Message = {
        data: function () {
            return {}
        },
        template: `
            <div>
                <div class="left-menu">
                    <div class="head">消息宝</div>
                    <router-link :to="{name:'Sop'}">SOP</router-link>
                    <router-link :to="{name:'Send'}">推送管理</router-link>
                </div>
                <div class="right-body">
                    <router-view></router-view>
                </div>

            </div>`
    };

    const Sop = {template: `<h3>SOP页面</h3>`};
    const Send = {template: `<h3>推送管理页面</h3>`};
    const Login = {
        data: function () {
            return {
                user: '',
                pwd: ''
            }
        },
        methods: {
            doLogin: function () {
                if (this.user.length > 0 && this.pwd.length > 0) {
                    sessionStorage.setItem("isLogin", true);
                    this.$router.push({name: 'Index'});
                }
            }
        },
        template: `
            <div style="width: 500px;margin: 100px auto">
                <input type="text" placeholder="用户名" v-model="user"/>
                <input type="text" placeholder="密码" v-model="pwd" />
                <input type="button" value="提 交"  @click="doLogin" />
            </div>
         `
    };
    const router = new VueRouter({
        routes: [
            {
                path: '/',
                component: Home,
                redirect: '/home'
            },
            {
                path: '/home',
                component: Home,
                name: "Home",
                children: [
                    {
                        path: '',
                        component: Index,
                        name: "Index"
                    },
                    {
                        path: 'task',
                        component: Task,
                        name: 'Task',
                        children: [
                            {
                                path: 'fans',
                                component: Fans,
                                name: 'Fans'
                            },
                            {
                                path: 'spread',
                                component: Spread,
                                name: 'Spread'
                            },
                            {
                                path: 'statistics',
                                component: Statistics,
                                name: 'Statistics'
                            }
                        ]
                    },
                    {
                        path: 'message',
                        component: Message,
                        name: 'Message',
                        children: [
                            {
                                path: 'sop',
                                component: Sop,
                                name: 'Sop'
                            },
                            {
                                path: 'send',
                                component: Send,
                                name: 'Send'
                            }
                        ]
                    }
                ],
                beforeEnter: (to, from, next) => {
                    if (sessionStorage.getItem('isLogin')) {
                        next();
                        return;
                    }
                    // 未登录,跳转登录页面
                    // next(false); 保持当前所在页面,不跳转
                    next({name: 'Login'});
                }
            },
            {path: '/login', component: Login, name: 'Login'},
        ]
    })

    var app = new Vue({
        el: '#app',
        data: {},
        methods: {},
        router: router
    })
</script>
</body>
</html>

# 补充:前端存储

  • cookie 有时效,可自动携带到发送请求中
  • localStorage 可一直存在 指导手动清空
    setItem (key, value)
    getItem (key)
    removeItem (key)
    clear ()
    key (index)
    
  • sessionStorage 页面关闭或浏览器关闭 清空
上次更新: 1/5/2023, 5:29:59 PM