国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 網站 > WEB開發 > 正文

Ember Route

2024-04-27 15:13:45
字體:
來源:轉載
供稿:網友

簡介

Ember Route,路由管理,在ember中具有很重要的意義,他負責管理整個路由的規則,什么時候應該渲染什么模板等,總體來說,他的功能有

渲染一個模板加載model以供模板使用重定向到一個新的路由,比如說權限控制情況下,一個人不允許訪問某一個頁面可以負責處理一個action(動作或者事件)

基本配置

創建route

使用命令行創建ember g route <your-route-name>; 執行命令后,會在app/templates目錄下生成模板,會在app/routes目錄下生成js文件,同時修改app/route.js文件。

這里主要說明一下route.js文件,其基本格式為:

Router.map(function() { this.route('path1'); this.route('favorites', { path: '/path2' });});

當訪問/path1的時候,渲染path1模板,當訪問/path2的時候,渲染favorites模板。 如果是嵌套的路由(子路由),比如path1/path2,那么形式可能是這樣的, 創建的時候只需要ember g route path1/path2

Router.map(function() { this.route('path1',function(){ this.route('path2'); });});

如果想要設置初始頁面,可以這樣,這樣就可以為/設置一個初始的路由:

Router.map(function() { this.route('index',{path:'/'});});

如果url中具有動態的參數呢?例如localhost:8000/path1/path2/2,這個2可能是一個id,又或者localhost:8000/path1/path2/2/edit這可能代表一個id為2的數據的編輯頁面,那么在route.js可以如下表示:

Router.map(function() { this.route('path1', function(){ this.route('path2',{path:'/path2/:id'}); });});

通過這種方式,就可以進行訪問,但是注意,以上的形式下localhost:8000/path1/path2是無法訪問的。 在這種情況下,如何使用這個id參數呢?

//app/routes/path1/path2export default Ember.Route.extend({ model(params){ let id = params.id; return this.store.findRecord('model-example',id).then((data)=>{return data}); }});

如上就可以對參數進行使用。理論上來講,是不能夠修改url中的參數的,所以手動賦值是無效的,也無法進行刷新等動作。同時需要注意,不要給參數起一樣的名字,那樣就會不起作用,下面的李自力有2個id,所以不會起作用:

Router.map(function() { this.route('photo', { path: '/photo/:id' }, function() { this.route('comment', { path: '/comment/:id' }); });});

路由、模板的渲染規則

所有的路由都有一個根的父路由:application,也就是說,我們創建的所有路由,都是經由application渲染的。 我們我們查看模板文件,會發現路由的模板的內容都是{{outlet}}。每一個模板都會渲染到父模板的{{outlet}}上。一層一層的往上渲染。 比如經典的圣杯模型,在我們看來,可能上邊欄側邊欄和下邊欄是不變的,那么我們可以定義我們的application.hbs為:

<div class="header">這是上邊欄</div><div class="sider">這是側邊欄</div><div class="content">{{outlet}}</div><div class="footer">這是下邊欄</div>

那么渲染的時候,只會渲染到content中。 接下來我們講解一下渲染的規則。這里這篇文章介紹的非常好Ember.js 入門指南之十四番外篇,路由、模板的執行、渲染順序

渲染其他的模板也是允許的

一般情況下,我們要渲染的模板都是自己的哪一個,但是,ember也允許你渲染其他的模板,例如正常情況下,不做任何操作,path1/path2渲染的模板就是app/templates/path1/path2.hbs, 但是如果你想要進行更換,只需要重載方法renderTemplate()

//app/routes/path1/path2.jsexport default Ember.Route.extend({ renderTemplate() { this.render('path1/path2', { into: 'templateName', outlet: 'anOutletName' }); //this.render('path3');//這個語句可以使用path3替換path1/path2 }});

上面這個方法可以將path1/path2渲染到templateName 中使用{{outlet 'anOutletName'}}的地方。詳情請見render。

model的執行順序

model的執行順序為從主到子。例如urlpath1/path2,那么model的執行順序為application->path1->path2

模板的渲染順序

首先,注意一點,就是,如果model執行完成后,才開始進行模板的渲染。 模板渲染的順序為從子到主,也就是path2->path1->application->path1。渲染完成后,展示。這里需要全部渲染完后展示。

路由的重定向

路由重定向,例如,當權限控制等的時候,跳轉到一個異常頁面等,常常會用到,常用方法為transitionTo()transitionTo()的表現和helperlink-to的表現一致。另外還有一個方法replaceWith(),使用起來差不多。

transitionTo()可以在各個階段使用:

//app/routes/path1.jsexport default Ember.Route.extend({ //在model初始化之前(發送請求之前) beforeModel(){ this.transitionTo('/path2'); }, //在初始化的時候, model(){ return this.findRecord('model-example',1).then((data)=>{ if(!data){ this.transitionTo('/path2'); }else{ return data; } }); } //在model初始化之后 afterModel(){ let model = this.modelFor('path1'); if(model.length){ this.transitionTo('/path2'); } }, actions:{ //可以在action中,比如點擊后 transitionToPath2(){ this.transitionTo('/path2'); } }});

如果是要重定向到子路由,也可以直接在beforeModel() afterModel() model()中進行,但是如果這樣的,考慮到子路由的執行過程,會再次將父路由執行一次,所有,ember有一個更加優化的方式redirect

//app/routes/path1.jsredirect(model, transition) { this.transitionTo('path1.path2');}

還有一些高級的用法,比如復雜url或者帶參數的情況,注意這種情況下不能使用replaceWith進行替換:

//路由為 this.route('path2',{path:path2/:id});this.transitionTo('/path2/2');this.transitionTo('/path2',2);//同上{{link-to 'path2' 2}}//路由為 this.route('path2',{path:path2/:id}, function(){this.route('path3',{path:'path3/:p_id'})});this.transitionTo('/path2/2/paht3/3');{{link-to 'path2' 2 3}}//路由為this.route('path2',{path:path2/:id}); 且有參數`queryParams`(這個概念會在controller中說)this.transitionTo('/path2/2?params=1');this.transitionTo('/path2/2',{queryParams: { params: '1' }});//同上{{link-to 'path2' 2 (query-params params='1')}}

終止與重試路由跳轉

有一些情況下,我們可能需要手動終止路由的跳轉,或者是終止之后再重試。

當用戶通過{{link-to}}、transition方法或者直接執行URL來轉換路由,當前路由會自動執行willTransition方法。每個活動的路由都可以決定是否執行轉換路由。 如果你正在填寫一個表單,然后,無意點擊了跳轉,這樣你的填寫的數據就都丟失了,很不友好。所以一般會有一個確認頁面。所以我們可以通過willTransition來先讓用戶確認是否離開再說。

// app/routes/path1.jsimport Ember from 'ember';export default Ember.Route.extend({ actions: { willTransition: function(transition) { if (!confirm("你確定要離開這個頁面嗎?")) { transition.abort(); } else { return true; } } }});

load 以及 error的處理

我們假設有這樣的一個model:slow-model,這個model返回結果非常的慢,那么我們的以routedemo1/case1為例,如果route中加載情況如下:

model(){ return this.store.findAll('slow-model').then((data)=>{ return data; });}

那么,在slow-model返回結果之前,頁面會一直是空白,這個非常不美觀,我們一般會采用一個loading的圖標或者有一個提示等。

Ember提供的解決辦法是:在beforeModel、model、afterModel回調還沒返回前先進入一個叫loading的子狀態,然后渲染一個叫<your-route-name>-loading的模板(如果是application路由則對應的直接是loading、error不需要前綴)。

同樣以demo1/path1為例:

//app/templates/application.hbs<p>application</p><p>application</p><p>application</p>{{outlet}}//app/routes/demo1.jsimport Ember from 'ember';export default Ember.Route.extend({ model() { return this.store.findAll('slow-model'); }})//app/templates/demo1.hbs<p>demo1</p><p>demo1</p><p>demo1</p>{{outlet}}//app/templates/demo1-loading.hbs<p>demo1-loading</p><p>demo1-loading</p><p>demo1-loading</p>//app/routes/demo1/case1.jsimport Ember from 'ember';export default Ember.Route.extend({ model() { return this.store.findAll('slow-model'); }//app/templates/demo1/case1.hbs<p>case1</p><p>case1</p><p>case1</p>//app/templates/demo1/case1-loading.hbs<p>case1-loading</p><p>case1-loading</p><p>case1-loading</p>

以上的代碼,假設slow-model是非常慢的,那么頁面的展示順序為:

這里寫圖片描述 這里寫圖片描述 這里寫圖片描述

demo1/case1為例,結合我們說過的路由渲染順序為,注意,渲染順序還是從子到父的: - demo1.case1-loading - demo1-loading - loading(application的loading)

從上圖可以看出,在model沒有加載好的時候,會先用<your-route-name>-loading來對本來的模板進行替換。那么在這個過程中,model的執行順序呢?這個過程中,model為先執行父route的model,也就是demo1的model,當請求發出,直到下一個子路由的mode請求發出,一直都是loading狀態,也就是: 這里寫圖片描述 然后子路由請求發出,也就是demo1/case1請求發出后,進入子路由的loading狀態: 這里寫圖片描述 數據返回后,結束: 這里寫圖片描述

另外,在beforeModel、model、afterModel回調沒有立即返回之前,會先執行一個名為loading的事件。

actions: { loading: function(transition, originRoute) { alert("Sorry this is taking so long to load!!"); } }

loading事件實在model回調返回之前執行。這里需要注意一下,如果同時定義了loading回調,以及<your-route-name>-loading子模板,那么會只執行loading回調,而不會渲染模板。

error的情況也類似,不過過程是在model返回且失敗的情況下,而loading為未返回的情況下: 以demo1/case1為例,結合我們說過的路由渲染順序為,注意,渲染順序還是從子到父的(考慮到model的執行順序,不會出現父吧子覆蓋的情況,因為執行不到- -): - demo1.case1-error - demo1-error - error(application的error)

error的回調為:

actions: { error(error, transition) { if (error.status === '403') { this.replaceWith('login'); } else { // Let the route above this handle the error. return true; } } }

查詢參數

動態路由的情況,我們已經說過,但是,如果是帶參數呢?舉例,我們常用的分頁操作,一般都會帶上pageSize=10&pageNum=2意味著第二頁取10個,這樣,那么在請求中怎么做呢? 這里就要使用到controller的概念,對于路由demo1/case1而言,如果要增加參數,那么就需要創建相應的controller。創建controller:ember g controller demo1/case1,以分頁為例:

//app/controllers/demo1/case1.jsimport Ember from 'ember';export default Ember.Controller.extend({ queryParams: ['pageSize','pageNum'], pageSize: null, pageNum:null});

這樣就會在請求上帶上這個參數,如果你沒帶的話,還是會取到這個參數,只不過都是null罷了。你可以為他們設置默認值:

//app/controllers/demo1/case1.jsimport Ember from 'ember';export default Ember.Controller.extend({ queryParams: ['pageSize','pageNum'], pageSize: 10, pageNum:1});

那么默認就是第一頁的10個。注意,如果你傳的值就是和默認的一樣,在請求上是不會展示的!

關于查詢參數的用法,跳轉,在之前的transitionTo()方法以及link-to助手的的時候已經說過。

controller中還可以調用model的數據,以及使用計算屬性,官網上給出一個例子:

import Ember from 'ember';export default Ember.Controller.extend({ queryParams: ['category'], category: null, filteredArticles: Ember.computed('category', 'model', function() { var category = this.get('category'); var articles = this.get('model'); if (category) { return articles.filterBy('category', category); } else { return articles; } })});

這樣,filteredArticles的值就會一直隨著model的改變而改變,而filteredArticles的值是可以直接在模板中使用的,所以說間接的導致模板元素的變化。

關于查詢參數,還有一個點很重要,就是更新數據。因為畢竟url改變了,如果數據卻沒有更新的話,簡直不合理。

上述的做法相當于這樣:

this.transitionTo({ queryParams: { pageNum: 3 }});{{link-to (query-param pageNum=3)}}

注意,這種方式,由于沒有修改路由的結構,只不過是修改了參數,所以只能說是不完整的路由切換,這種不完整,也就意味著比如model和setupController回調方法就不會被執行,只是使得controller里的屬性值為新的查詢參數值以及更新URL。(當然,如果是跳轉到一個新的路由,還是會改變的)。

如果單純的按照上面的寫法,model是不會更新的。那么如何更新model中的數據呢?這需要你在對應的路由中配置一個名為queryParams哈希對象。并且需要設置一個名為refreshModel的查詢參數,這個參數的值為true。

import Ember from 'ember';export default Ember.Route.extend({ queryParams: { category: { refreshModel: true } }, model(params) { // This gets called upon entering 'articles' route // for the first time, and we opt into refiring it upon // query param changes by setting `refreshModel:true` above. // params has format of { category: "someValueOrJustNull" }, // which we can forward to the server. return this.get('store').query('article', params); }});

那么每次你修改參數后,都會更新model并且執行setupController。但是要注意,這個也會同時刷新父路由!

那么如果要手動觸發呢?比如搜索條件,你想要點擊搜索的時候才更新數據,或者說只更新自己的路由的信息,怎么辦呢?那么可以這么做

import Ember from 'ember';export default Ember.Route.extend({ model(){ console.log('model'); }, setupCotroller(controller,model){ console.log('setupcontroller'); }, actions:{ //如果只需要更新model clickAction(){ this.refresh(); }, //同時更新model以及setupcontroller clickAction1(){ let self = this, controller=this.get('controller'); this.model().then((data)=>{ controller.set('model', data); self.setupController(controller,data); }) } }});

異步路由

//TODO


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 阳泉市| 盐亭县| 娱乐| 左贡县| 新闻| 那曲县| 福泉市| 宽城| 吉木萨尔县| 昌宁县| 西平县| 五大连池市| 陈巴尔虎旗| 三台县| 华蓥市| 博白县| 梅州市| 勐海县| 什邡市| 中江县| 顺平县| 镇康县| 延川县| 浠水县| 邢台县| 屏山县| 大冶市| 临漳县| 格尔木市| 米林县| 元氏县| 固始县| 当雄县| 福贡县| 石渠县| 阜南县| 徐水县| 泾源县| 永安市| 阿巴嘎旗| 涟源市|