本篇繼續(xù)介紹vue-router,我們需要要完成這樣個demo:《分頁顯示文章列表》;這里我們以博客園首頁列表為例簡化處理:

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

按照上圖框選所示,簡單分為藍(lán)色部分文章組件(ArticleItemComponent),橙色框選部分列表組件(ArticleListComponent);分頁部分我們就簡單通過router-link指令構(gòu)建滿足演示即可,我們的代碼實(shí)現(xiàn)邏輯:

1、列表組件初始化數(shù)據(jù),傳遞給文章組件進(jìn)行渲染

2、路由改變時重新初始化列表組件,更新數(shù)據(jù)

請看我們的第一版代碼:

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

<!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: `一步一步學(xué)習(xí)Vue (${i})`,
                    desc: `一步一步學(xué)習(xí)Vue---正文部分 (${i})---正文結(jié)束`,
                    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;                    //假定每頁五條數(shù)據(jù)
                    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>

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

  路由的配置方式上一篇文章中已經(jīng)做過介紹,這里陌生的部分在于ArticleListComponent中的created的使用,一個vue實(shí)例被生成后調(diào)用這個函數(shù)。vue實(shí)例被生成后還要綁定到某個html元素上,之后還要進(jìn)行編譯,然后再插入到document中。每一個階段都會有一個鉤子函數(shù),方便開發(fā)者在不同階段處理不同邏輯;其它鉤子函數(shù)我們在使用的時候會繼續(xù)介紹。一般可以在created函數(shù)中調(diào)用ajax等來獲取頁面初始化所需的數(shù)據(jù)。

  雙擊運(yùn)行,效果如下圖所示:

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

  我們發(fā)現(xiàn),就在第一次初始化的時候,文章列表正常顯示出來了,但是后面路由的切換操作,并沒有引起組件的更新或者說數(shù)據(jù)的更新?這是什么原因呢?其實(shí)在vue-router會最大的限度的重用組件,也就是說當(dāng)page/1 and page/2這兩個路徑之間切換的時候,vue-router發(fā)現(xiàn)映射的是同一個組件,那么vue-router就會重用該組件,而不會重新創(chuàng)建它,因?yàn)楸绕痄N毀再創(chuàng)建,復(fù)用則顯得更加高效,所以組件的created鉤子函數(shù)就不會被執(zhí)行,導(dǎo)致數(shù)據(jù)不會更新,從而出現(xiàn)上圖的結(jié)果;對于上述現(xiàn)象vue-router也給我們提供了解決方式,上文提到了在vue-router啟用之后,$route會被注入到任何組件,那么我們就可以監(jiān)聽$roue組件的變化來實(shí)現(xiàn)組件更新,基于此,請看我們的第二版代碼(請看綠色部分)

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

//....省略其它代碼 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;                    //假定每頁五條數(shù)據(jù)
                    var start = (index - 1) * 5,
                        end = index * 5;                    this.articleList = fakeData.slice(start, end);
                }
            },            watch: {                '$route': function () {                    this.activePagedData();

                }
            },

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

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

 

保存后刷新,效果應(yīng)該是這樣的:

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

這個是一個不大不小的坑,而且這種使用場景我們在實(shí)際生產(chǎn)中也很常見,當(dāng)你發(fā)現(xiàn)路由變化的時候,組件數(shù)據(jù)未更新,可以考慮由于組件重用導(dǎo)致的生命周期鉤子未執(zhí)行的情況,當(dāng)然解決方式也不止這一種,在vue-router 2.2+中也增加了鉤子函數(shù)同樣能解決問題。而且通過watch方式有點(diǎn)侵入,感覺和在angular中使用watch類似,個人不推薦這種寫法;我們簡單修改下我們程序,作為本篇代碼的最后一版本:

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

 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;                    //假定每頁五條數(shù)據(jù)
                    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
            }
        }

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

保存后刷新頁面,可以發(fā)現(xiàn)效果和上圖一致。

小結(jié):今天就到這里吧,主要講了一個知識點(diǎn),如何處理vue'-router導(dǎo)致的組件重用問題,組件重用很多場景下提供了很好的性能指標(biāo),畢竟操作dom的代價是很大的,但是總要解決類似上述場景的問題,雖然是一個很小的知識點(diǎn),但值得單獨(dú)放一篇著重說明一下,下一篇會講述生命周期(牽扯到組件生命周期和路由生命周期),敬請期待。

本篇繼續(xù)介紹vue-router,我們需要要完成這樣個demo:《分頁顯示文章列表》;這里我們以博客園首頁列表為例簡化處理:

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

按照上圖框選所示,簡單分為藍(lán)色部分文章組件(ArticleItemComponent),橙色框選部分列表組件(ArticleListComponent);分頁部分我們就簡單通過router-link指令構(gòu)建滿足演示即可,我們的代碼實(shí)現(xiàn)邏輯:

1、列表組件初始化數(shù)據(jù),傳遞給文章組件進(jìn)行渲染

2、路由改變時重新初始化列表組件,更新數(shù)據(jù)

請看我們的第一版代碼:

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

<!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: `一步一步學(xué)習(xí)Vue (${i})`,
                    desc: `一步一步學(xué)習(xí)Vue---正文部分 (${i})---正文結(jié)束`,
                    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;                    //假定每頁五條數(shù)據(jù)
                    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>

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

  路由的配置方式上一篇文章中已經(jīng)做過介紹,這里陌生的部分在于ArticleListComponent中的created的使用,一個vue實(shí)例被生成后調(diào)用這個函數(shù)。vue實(shí)例被生成后還要綁定到某個html元素上,之后還要進(jìn)行編譯,然后再插入到document中。每一個階段都會有一個鉤子函數(shù),方便開發(fā)者在不同階段處理不同邏輯;其它鉤子函數(shù)我們在使用的時候會繼續(xù)介紹。一般可以在created函數(shù)中調(diào)用ajax等來獲取頁面初始化所需的數(shù)據(jù)。

  雙擊運(yùn)行,效果如下圖所示:

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

  我們發(fā)現(xiàn),就在第一次初始化的時候,文章列表正常顯示出來了,但是后面路由的切換操作,并沒有引起組件的更新或者說數(shù)據(jù)的更新?這是什么原因呢?其實(shí)在vue-router會最大的限度的重用組件,也就是說當(dāng)page/1 and page/2這兩個路徑之間切換的時候,vue-router發(fā)現(xiàn)映射的是同一個組件,那么vue-router就會重用該組件,而不會重新創(chuàng)建它,因?yàn)楸绕痄N毀再創(chuàng)建,復(fù)用則顯得更加高效,所以組件的created鉤子函數(shù)就不會被執(zhí)行,導(dǎo)致數(shù)據(jù)不會更新,從而出現(xiàn)上圖的結(jié)果;對于上述現(xiàn)象vue-router也給我們提供了解決方式,上文提到了在vue-router啟用之后,$route會被注入到任何組件,那么我們就可以監(jiān)聽$roue組件的變化來實(shí)現(xiàn)組件更新,基于此,請看我們的第二版代碼(請看綠色部分)

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

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

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