Ember 番外篇,路由、模板的執(zhí)行、渲染順序

2018-01-06 17:38 更新

在Ember中路由和模板的執(zhí)行都是有一定順序的,它們的順序?yàn)椋褐髀酚?>子路由1->子路由2->子路由3->……。模板渲染的順序與路由執(zhí)行順序剛好相反,從最后一個(gè)模板開(kāi)始解析渲染。

注意:模板的渲染是在所有路由執(zhí)行完之后,從最后一個(gè)模板開(kāi)始。關(guān)于這一點(diǎn)下面的代碼會(huì)演示驗(yàn)證,官網(wǎng)教程有介紹,點(diǎn)擊查看。

比如有一路由格式為application/posts/detail/comments/comment,此時(shí)路由執(zhí)行的順序?yàn)椋?code>application/posts -> detail -> comments -> comment,application是項(xiàng)目默認(rèn)的路由,用戶自定義的所有路由都是application的子路由(默認(rèn)情況下),相對(duì)應(yīng)的模板也是這樣,所有用戶自定義的模板都是application.hbs的子模板。如果你要修改模板的渲染層次你可以在route中重寫(xiě)renderTemplate回調(diào)函數(shù),在函數(shù)內(nèi)使用render方法指定要渲染的模板(如:render('other'),渲染到other這個(gè)模板上)更多有關(guān)信息請(qǐng)查看這里。并且它們對(duì)應(yīng)的文件模板結(jié)構(gòu)如下圖:

文件模板結(jié)構(gòu)

路由與模板是相對(duì)應(yīng)的,所以模板的目錄結(jié)構(gòu)與路由的目錄結(jié)構(gòu)是一致的。 你有兩種方式構(gòu)建上述目錄:

  1. 手動(dòng)創(chuàng)建
  2. 使用命令,比如創(chuàng)建comment.js使用命令:ember generate route posts/detail/comments/comment,Ember CLI會(huì)自動(dòng)為我們創(chuàng)建目錄和文件。

創(chuàng)建好目錄結(jié)構(gòu)之后我們添加一些代碼到每個(gè)文件。運(yùn)行項(xiàng)目之后你就會(huì)一目了然了……。 下面我按前面講的路由執(zhí)行順序分別列出每個(gè)文件的內(nèi)容。

//  app/routes/posts.js


import Ember from 'ember';


export default Ember.Route.extend({
    model: function() { 
        console.log('running in posts...');
        return { id: 1, routeName: 'The route is posts'};
        // return Ember.$.getJSON('https://api.github.com/repos/emberjs/ember.js/pulls');
    }

    
});

import Ember from 'ember';


export default Ember.Route.extend({


    model: function(params) {
        console.log('params id = ' + params.post_id);
        console.log('running in detail....');


        return { id: 1, routeName: 'The route is detail..' };
    }
}); 

//  app/routes/posts/detail.js


import Ember from 'ember';


export default Ember.Route.extend({


    model: function(params) {
        console.log('params id = ' + params.post_id);
        console.log('running in detail....');


        return { id: 1, routeName: 'The route is detail..' };
    }
}); 

//  app/routes/posts/detail/comments.js


import Ember from 'ember';


export default Ember.Route.extend({
    model: function() {
        console.log('running in comments...');
        return { id: 1, routName: 'The route is comments....'};
    }
});

//  app/routes/posts/detail/comments/comment.js


import Ember from 'ember';


export default Ember.Route.extend({
    model: function(params) {
        console.log('params id = ' + params.post_id);
        console.log('running in comment...');
        return { id: 1, routeName: 'The route is comment...'};
    }
});

下面是模板各個(gè)文件的內(nèi)容。其列出才順序與路由的順序一致。







{{model.routeName}} >> {{outlet}}







{{model.routeName}} >> {{outlet}}







{{model.routeName}} >> {{outlet}}






{{model.routeName}} >> {{outlet}}

下圖是路由執(zhí)行的順序,并且在執(zhí)行的過(guò)程中渲染路由對(duì)應(yīng)的模板。

路由執(zhí)行的順序

從上圖中可用清楚的看到當(dāng)你運(yùn)行一個(gè)URL時(shí),與URL相關(guān)的路由是怎么執(zhí)行的。

  1. 執(zhí)行主路由(默認(rèn)是application),此時(shí)進(jìn)入到路由的model回調(diào)方法,并且返回了一個(gè)對(duì)象{ id: 1, routeName: 'The route is application...' },執(zhí)行完回調(diào)之后繼續(xù)轉(zhuǎn)到子路由執(zhí)行直到最后一個(gè)路由執(zhí)行完畢,所有的路由執(zhí)行完畢之后開(kāi)始渲染頁(yè)面。
  2. 頁(yè)面的渲染則是從最后一個(gè)路由對(duì)應(yīng)的模板開(kāi)始,并沿著最近的父模板往回渲染。 為了驗(yàn)證是否是這樣的執(zhí)行順序,下面修改detail.jscomments.js。在代碼中加入一個(gè)模擬休眠的操作。
    
    //  app/routes/posts/detail.js

import Ember from 'ember';

export default Ember.Route.extend({

model: function(params) { console.log('params id = ' + params.post_id); console.log('running in detail....');

// 執(zhí)行一個(gè)循環(huán),模擬休眠 for (var i = 0; i < 10000000000; i++) {

        
    }
    console.log('The comment route executed...');

return { id: 1, routeName: 'The route is detail..' }; } });

```javascript
//  app/routes/posts/detail/comments.js


import Ember from 'ember';


export default Ember.Route.extend({
    model: function(params) {
        console.log('params id = ' + params.post_id);
        console.log('running in comment...'); 
        //  執(zhí)行一個(gè)循環(huán),模擬休眠
        for (var i = 0; i < 10000000000; i++) {

            
        }


        return { id: 1, routeName: 'The route is comment...'};
    }
});

刷新頁(yè)面,注意查看控制臺(tái)輸出信息和頁(yè)面顯示的內(nèi)容。 新開(kāi)一個(gè)窗口,執(zhí)行URL:http://localhost:4200/posts/2/comments

run result

控制臺(tái)輸出到這里時(shí)處理等待(執(zhí)行for循環(huán)),此時(shí)已經(jīng)執(zhí)行了兩個(gè)路由applicationposts,并且正在執(zhí)行detail,但是頁(yè)面是空白的,沒(méi)有任何HTML元素。

run result

detail路由執(zhí)行完成之后轉(zhuǎn)到路由comments。然后執(zhí)行到for循環(huán)模擬休眠,此時(shí)頁(yè)面仍然是沒(méi)有任何HTML元素。然后等到所有route執(zhí)行完畢之后,界面才顯示model回調(diào)里設(shè)置的信息。

run result

run result

每個(gè)子路由設(shè)置的信息都會(huì)渲染到最近一個(gè)父路由對(duì)應(yīng)模板的{{outlet}}上面。

run result

  1. 渲染comment 得到的內(nèi)如為:“comment渲染完成”
  2. 渲染comment最近的父模板comments 得到的內(nèi)容為:“comment渲染完成 comments渲染完成”
  3. 渲染comments最近的父模板detail 得到的內(nèi)容為:“comment渲染完成 comments渲染完成 detail渲染完成”
  4. 渲染detail最近的父模板posts 得到的內(nèi)容為:“comment渲染完成 comments渲染完成 detail渲染完成 posts渲染完成”
  5. 渲染posts最近的父模板application 得到的內(nèi)容為:“comment渲染完成 comments渲染完成 detail渲染完成 posts渲染完成 application渲染完成”

只要記住一句話:子模板的都會(huì)渲染到父模板的{{outlet}}上,最終所有的模板都會(huì)被渲染到application{{outlet}}上。


博文完整代碼放在Github(博文經(jīng)過(guò)多次修改,博文上的代碼與github代碼可能又出入,不過(guò)影響不大?。绻阌X(jué)得博文對(duì)你有點(diǎn)用,請(qǐng)?jiān)趃ithub項(xiàng)目上給我點(diǎn)個(gè)star吧。您的肯定對(duì)我來(lái)說(shuō)是最大的動(dòng)力??!

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)