本篇继续介绍vue-router,我们需要要完成这样个demo:《分页显示文章列表》;这里我们以博客园首页列表为例简化处理:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

按照上图框选所示,简单分为蓝色部分文章组件(ArticleItemComponent),橙色框选部分列表组件(ArticleListComponent);分页部分我们就简单通过router-link指令构建满足演示即可,我们的代码实现逻辑:

1、列表组件初始化数据,传递给文章组件进行渲染

2、路由改变时重新初始化列表组件,更新数据

请看我们的第一版代码:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>demo2</title>
    <script src="https://cdn.bootcss.com/vue/2.4.1/vue.js"></script>
    <script src="https://cdn.bootcss.com/vue-router/2.7.0/vue-router.js"></script>
    <style>
        .active{
            color: red;
        }
    </style></head><body>
    <div id="app">
        <router-link v-for="n in [1,2,3,4,5,6,7,8]" :to="{name:'page',params:{num:n}}" :key="n">&nbsp;{{n}}&nbsp;</router-link>
        <div>
            <router-view>
            </router-view>
        </div>

    </div>

    <script>
        var fakeData = [];
        (function () {            for (var i = 0; i < 45; i++) {
                fakeData.push({
                    id: i + 1,
                    title: `一步一步学习Vue (${i})`,
                    desc: `一步一步学习Vue---正文部分 (${i})---正文结束`,
                    readcount: parseInt(Math.random() * 1000)
                })
            }
        })();        var ArticleItemComponent = {
            template: `            <ul class="article-item">
                <li>{{item.readcount}}</li>
                <li>{{item.title}}</li>
                <li>{{item.desc}}</li>
            </ul>        `,
            props: ['item']
        }        var ArticleListComponent = {
            template: `            <div class="article-list">
                <article-item v-for="item in articleList" :item="item" :key="item.id"></article-item>
            </div>        `,
            data: function () {                return {
                    articleList: []
                }
            },
            created: function () {                this.activePagedData();

            },

            methods: {
                activePagedData: function () {                    var index = this.$route.params.num;                    //假定每页五条数据
                    var start = (index - 1) * 5,
                        end = index * 5;                    this.articleList = fakeData.slice(start, end);
                }
            },

           

            components: {                'article-item': ArticleItemComponent
            }
        }        var router = new VueRouter({
            linkActiveClass:'active',
            routes: [
                { name: 'page', path: '/page/:num', component: ArticleListComponent }
            ]
        });        var app = new Vue({
            router: router
        }).$mount("#app");    </script></body></html>

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

  路由的配置方式上一篇文章中已经做过介绍,这里陌生的部分在于ArticleListComponent中的created的使用,一个vue实例被生成后调用这个函数。vue实例被生成后还要绑定到某个html元素上,之后还要进行编译,然后再插入到document中。每一个阶段都会有一个钩子函数,方便开发者在不同阶段处理不同逻辑;其它钩子函数我们在使用的时候会继续介绍。一般可以在created函数中调用ajax等来获取页面初始化所需的数据。

  双击运行,效果如下图所示:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

  我们发现,就在第一次初始化的时候,文章列表正常显示出来了,但是后面路由的切换操作,并没有引起组件的更新或者说数据的更新?这是什么原因呢?其实在vue-router会最大的限度的重用组件,也就是说当page/1 and page/2这两个路径之间切换的时候,vue-router发现映射的是同一个组件,那么vue-router就会重用该组件,而不会重新创建它,因为比起销毁再创建,复用则显得更加高效,所以组件的created钩子函数就不会被执行,导致数据不会更新,从而出现上图的结果;对于上述现象vue-router也给我们提供了解决方式,上文提到了在vue-router启用之后,$route会被注入到任何组件,那么我们就可以监听$roue组件的变化来实现组件更新,基于此,请看我们的第二版代码(请看绿色部分)

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

//....省略其它代码 var ArticleListComponent = {
            template: `            <div class="article-list">
                <article-item v-for="item in articleList" :item="item" :key="item.id"></article-item>
            </div>        `,
            data: function () {                return {
                    articleList: []
                }
            },
            created: function () {                this.activePagedData();

            },

            methods: {
                activePagedData: function () {                    var index = this.$route.params.num;                    //假定每页五条数据
                    var start = (index - 1) * 5,
                        end = index * 5;                    this.articleList = fakeData.slice(start, end);
                }
            },            watch: {                '$route': function () {                    this.activePagedData();

                }
            },

            components: {                'article-item': ArticleItemComponent
            }
        }//......省略其它

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

 

保存后刷新,效果应该是这样的:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

这个是一个不大不小的坑,而且这种使用场景我们在实际生产中也很常见,当你发现路由变化的时候,组件数据未更新,可以考虑由于组件重用导致的生命周期钩子未执行的情况,当然解决方式也不止这一种,在vue-router 2.2+中也增加了钩子函数同样能解决问题。而且通过watch方式有点侵入,感觉和在angular中使用watch类似,个人不推荐这种写法;我们简单修改下我们程序,作为本篇代码的最后一版本:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

 var ArticleListComponent = {
            template: `            <div class="article-list">
                <article-item v-for="item in articleList" :item="item" :key="item.id"></article-item>
            </div>        `,
            data: function () {                return {
                    articleList: []
                }
            },
            created: function () {                this.activePagedData();

            },

            methods: {
                activePagedData: function () {                    var index = this.$route.params.num;                    //假定每页五条数据
                    var start = (index - 1) * 5,
                        end = index * 5;                    this.articleList = fakeData.slice(start, end);
                }
            },            // watch: {
            //     '$route': function () {
            //         this.activePagedData();

            //     }
            // },
            beforeRouteUpdate: function (to, from, next) {                this.activePagedData();
                next();
            },
            components: {                'article-item': ArticleItemComponent
            }
        }

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

保存后刷新页面,可以发现效果和上图一致。

小结:今天就到这里吧,主要讲了一个知识点,如何处理vue'-router导致的组件重用问题,组件重用很多场景下提供了很好的性能指标,毕竟操作dom的代价是很大的,但是总要解决类似上述场景的问题,虽然是一个很小的知识点,但值得单独放一篇着重说明一下,下一篇会讲述生命周期(牵扯到组件生命周期和路由生命周期),敬请期待。

本篇继续介绍vue-router,我们需要要完成这样个demo:《分页显示文章列表》;这里我们以博客园首页列表为例简化处理:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

按照上图框选所示,简单分为蓝色部分文章组件(ArticleItemComponent),橙色框选部分列表组件(ArticleListComponent);分页部分我们就简单通过router-link指令构建满足演示即可,我们的代码实现逻辑:

1、列表组件初始化数据,传递给文章组件进行渲染

2、路由改变时重新初始化列表组件,更新数据

请看我们的第一版代码:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>demo2</title>
    <script src="https://cdn.bootcss.com/vue/2.4.1/vue.js"></script>
    <script src="https://cdn.bootcss.com/vue-router/2.7.0/vue-router.js"></script>
    <style>
        .active{
            color: red;
        }
    </style></head><body>
    <div id="app">
        <router-link v-for="n in [1,2,3,4,5,6,7,8]" :to="{name:'page',params:{num:n}}" :key="n">&nbsp;{{n}}&nbsp;</router-link>
        <div>
            <router-view>
            </router-view>
        </div>

    </div>

    <script>
        var fakeData = [];
        (function () {            for (var i = 0; i < 45; i++) {
                fakeData.push({
                    id: i + 1,
                    title: `一步一步学习Vue (${i})`,
                    desc: `一步一步学习Vue---正文部分 (${i})---正文结束`,
                    readcount: parseInt(Math.random() * 1000)
                })
            }
        })();        var ArticleItemComponent = {
            template: `            <ul class="article-item">
                <li>{{item.readcount}}</li>
                <li>{{item.title}}</li>
                <li>{{item.desc}}</li>
            </ul>        `,
            props: ['item']
        }        var ArticleListComponent = {
            template: `            <div class="article-list">
                <article-item v-for="item in articleList" :item="item" :key="item.id"></article-item>
            </div>        `,
            data: function () {                return {
                    articleList: []
                }
            },
            created: function () {                this.activePagedData();

            },

            methods: {
                activePagedData: function () {                    var index = this.$route.params.num;                    //假定每页五条数据
                    var start = (index - 1) * 5,
                        end = index * 5;                    this.articleList = fakeData.slice(start, end);
                }
            },

           

            components: {                'article-item': ArticleItemComponent
            }
        }        var router = new VueRouter({
            linkActiveClass:'active',
            routes: [
                { name: 'page', path: '/page/:num', component: ArticleListComponent }
            ]
        });        var app = new Vue({
            router: router
        }).$mount("#app");    </script></body></html>

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

  路由的配置方式上一篇文章中已经做过介绍,这里陌生的部分在于ArticleListComponent中的created的使用,一个vue实例被生成后调用这个函数。vue实例被生成后还要绑定到某个html元素上,之后还要进行编译,然后再插入到document中。每一个阶段都会有一个钩子函数,方便开发者在不同阶段处理不同逻辑;其它钩子函数我们在使用的时候会继续介绍。一般可以在created函数中调用ajax等来获取页面初始化所需的数据。

  双击运行,效果如下图所示:

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

  我们发现,就在第一次初始化的时候,文章列表正常显示出来了,但是后面路由的切换操作,并没有引起组件的更新或者说数据的更新?这是什么原因呢?其实在vue-router会最大的限度的重用组件,也就是说当page/1 and page/2这两个路径之间切换的时候,vue-router发现映射的是同一个组件,那么vue-router就会重用该组件,而不会重新创建它,因为比起销毁再创建,复用则显得更加高效,所以组件的created钩子函数就不会被执行,导致数据不会更新,从而出现上图的结果;对于上述现象vue-router也给我们提供了解决方式,上文提到了在vue-router启用之后,$route会被注入到任何组件,那么我们就可以监听$roue组件的变化来实现组件更新,基于此,请看我们的第二版代码(请看绿色部分)

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

//....省略其它代码 var ArticleListCompon

http://www.cnblogs.com/Johnzhang/p/7237065.html

延伸阅读

投入六个月的经历,收获了整个人生-Java培训,做最负责任的教育,学习改变命运,软件学习,再就业,大学生如何就业,帮大学生找到好工作,lphotoshop培训,电脑培训,电脑维修培训,移动软件开发培训,网站设计培训,网站建设培训投入六个月的经历,收获了整个人生