單頁面應用程序:使用一個進加載一次的網頁,若是頁面因爲用戶的交互而改變,則僅繪製更改的頁面部分。css
要建立單頁面應用程序須要使用 oj.Router 的虛擬導航來支持,ojModule 用來響應頁面的從新繪製。 ojModule 僅用於分離的 view 和 viewMode ,使之與頁面經過 Knockout綁定。另外,ojModule 可選,當不使用分離視圖與模型時,可直接在元素上響應變化。html
當選擇 Chapter1 或其餘時,將顯示新內容,而且URL更改以反映用戶在頁面上當前的位置。web
路由器帶有兩個URL適配器。每一個適配器定義如何將URL格式化表示。數組
urlPathAdapter:在路徑段中格式化 URL 。每一個段都是的當前狀態 id ,由 ‘ / ’ 分隔,如: localhost:8000/chap1瀏覽器
urlParamAdapter:使用查詢參數格式化 URL 。每一個參數都是路由器名稱及其當前狀態 id ,如:localhost:8000/?root=chap1服務器
路由器的默認適配器是 urlPathAdapter 。須要更改能夠使用 方法:app
oj.Router.defaults['urlAdapter'] = new oj.Router.urlParamAdapterflex
當路由單頁應用程序時,頁面不會從頭開始加載,但頁面內容會動態更改。爲了成爲瀏覽器歷史的一部分並提供書籤內容,Oracle JET 路由器模擬使用 HTML5 歷史記錄推送狀態功能導航的行爲。路由器還控制 URL 看起來像傳統頁面 URL。 這些 URL 沒有資源,必須設置 HTML 服務器。這是經過一個重寫引擎的簡單規則完成的。ui
通常來講,當應用程序中用戶需求只包含幾個視圖而且關聯狀態不是很複雜,則使用查詢參數。而路徑段顯示 URL 則顯得 URL 更簡潔,特別是使用嵌套路徑(添加子路由)。this
ojModule 與 oj.Router 結合使用,能夠配置 ojModule 對象,其中模塊名稱是路由器的狀態。當路由器更改狀態時,ojModule 將自動加載並呈現當前 RouterState 對象的值得指定模塊內容。
(1)appController.js:
define(['ojs/ojcore', 'knockout', 'ojs/ojknockout', 'ojs/ojrouter', 'ojs/ojbutton', 'ojs/ojtoolbar'],
function(oj, ko) {
function ControllerViewModel() {
var self = this;
self.router = oj.Router.rootInstance;
self.router.configure({
'pref': { label: 'Preface', isDefault: true},
'chap1': { label: 'Chapter 1'},
'chap2': { label: 'Chapter 2'},
'chap3' : {label: 'Chapter 3'}
});
oj.Router.defaults['urlAdapter'] = new oj.Router.urlParamAdapter;
}
return new ControllerViewModel();
}
);
a)添加 ojrouter 模塊。
'ojs/ojrouter'
b)建立路由實例,oj.Router.rootInstance 表示惟一根路由,該路由的名稱是 「root」 。
self.router = oj.Router.rootInstance;
c)配置路由器狀態,屬性: label:連接字符串,沒有定義標題屬性時,用於頁面的標題。
value:與該狀態相關聯的對象。
isDefault:設置起始頁面
self.router.configure({
'pref': { label: 'Preface', isDefault: true},
'chap1': { label: 'Chapter 1'},
'chap2': { label: 'Chapter 2'},
'chap3' : {label: 'Chapter 3'}
});
d)URL適配器,可選。
oj.Router.defaults['urlAdapter'] = new oj.Router.urlParamAdapter;
(2)main.js
require(['ojs/ojcore', 'knockout', 'appController', 'ojs/ojknockout', 'ojs/ojrouter', 'ojs/ojmodule'], function (oj, ko, app) { $(function() { oj.Router.sync().then( function() { ko.applyBindings(app, document.getElementById('routingContainer')); }, function(error) { oj.Logger.error('Error in root start: ' + error.message); } ); }); } );
a)添加 ojrouter 模塊和 ojmodule(須要使用 ojmodule 時添加)
'ojs/ojrouter', 'ojs/ojmodule'
b)將路由器與當前 URL 同步。必須在路由器配置後才能調用,以將 URL 與路由器狀態同步。
oj.Router.sync().then()
c)將 appController 掛載到 HTML 上
ko.applyBindings(app, document.getElementById('routingContainer'))
(3)index.html
<div id="routing-container"> <div id='buttons-container' data-bind="ojComponent: {component:'ojToolbar'}"> <div data-bind="ojComponent: { component: 'ojButtonset', checked: router.stateId, focusManagement: 'none'}"> <!-- ko foreach: router.states --> <label data-bind="attr: {for : id}"></label> <input type="radio" name="chapter" data-bind="value: id, attr: { id: id}, ojComponent: { component: 'ojButton', label: label}"/> <!-- /ko --> </div> </div> <div data-bind="ojModule: router.moduleConfig"></div> </div>
a)選擇時觸發狀態轉換
定義 checked 屬性給予 router.stateId 觀察值。它使用雙向綁定。當點擊一個按鈕時,id 被寫入到 stateId 中,使路由器狀態轉換。
b)觀察狀態並更新相關部分
data-bind="ojModule: router.moduleConfig"
使用須要建立相應的 views 和 viewModels
c) router.states 能夠獲取到路由配置轉化的數組以供遍歷展現內容
(4)實際效果如前簡單模型相同。
(1)appController.js
define(['ojs/ojcore', 'knockout', 'ojs/ojknockout', 'ojs/ojrouter', 'ojs/ojbutton', 'ojs/ojtoolbar', 'ojs/ojnavigationlist'], function(oj, ko) { function ControllerViewModel() { var self = this; // 建立根路由 self.shapeRouter = oj.Router.rootInstance; self.shapeRouter.configure({ 'square': { label: 'Square', isDefault: true }, 'circle': { label: 'Circle' }, 'oval': { label: 'Oval'} }); // 建立子路由配置 self.colorRouter = self.shapeRouter.createChildRouter('color').configure({ 'red': { label: 'Red', isDefault: true }, 'blue': { label: 'Blue' }, 'green': {label: 'Green'} }); self.menuItemSelect = function(event, ui) { self.shapeRouter.go(ui.item.children('a').text()); } } return new ControllerViewModel(); } );
a)建立根路由
b)建立子路由並配置
使用 createChildRouter('name') 建立子路由並添加 configure 配置。
(function(event, ui) 這裏的 event, ui 是 select 帶有的屬性。另外 optionhange 等也有這兩屬性)
(2)main.js 與上例相同
(3)index.html
<div id="routing-container"> <!-- 導航欄部分 --> <div id="toolbar" data-bind="ojComponent: { component: 'ojToolbar'}"> <!-- 父路由導航欄部分 --> <div data-bind="ojComponent: { component: 'ojButtonset', checked: shapeRouter.stateId, focusManagement: 'none' }"> <!-- ko foreach: shapeRouter.states --> <label data-bind="attr: {for: id}"></label> <input type="radio" name="shape" data-bind="value: id, attr: { id: id}, ojComponent: {component: 'ojButton', label: label}"></input> <!-- /ko --> </div> <!-- 直接跳轉指定位置 --> <button id="menuButton" data-bind="ojComponent: { component: 'ojButton', label: 'Go to', menu: '#gotoMenu'}"> </button> <!-- 列表顯示跳轉位置 --> <ul id="gotoMenu" style="display: none" data-bind="ojComponent: { component: 'ojMenu', select: menuItemSelect }"> <!-- ko foreach: shapeRouter.states --> <li> <a data-bind="text: label"></a> <ul data-bind="foreach: $root.colorRouter.states"> <li> <a data-bind="text: '/' + $parent.id + '/' + id"></a> </li> </ul> </li> <!-- /ko --> </ul> </div> <hr/> <!-- 展現部分 --> <div id="pageContent" class="oj-flex oj-flex-items-pad"> <!-- 子路由導航欄 --> <div class="oj-xl-2 oj-lg-2 oj-md-2 oj-sm-12 oj-flex-item"> <div id="colors" data-bind="ojComponent: { component: 'ojNavigationList', selection: colorRouter.stateId, drillMode: 'none'}"> <ul data-bind="foreach: colorRouter.states"> <li data-bind="attr: {id: id}"> <a data-bind="text: label"></a> </li> </ul> </div> </div> <!-- 圖形顯示 --> <div class="oj-xl-10 oj-md-10 oj-sm-12 oj-flex-item"> <div data-bind="css: shapeRouter.stateId(), style: { background: colorRouter.stateId() }"></div> </div> </div> </div>
a)stateId 能夠讓 knockout 觀察,而 steteId() 則能夠讀取當前的 Id 的值。
(4)CSS
.square { width: 100px; height: 100px; } .circle { width: 100px; height: 100px; -moz-border-radius: 50px; -webkit-border-radius: 50px; border-radius: 50px; } .oval { width: 200px; height: 100px; -moz-border-radius: 100px / 50px; -webkit-border-radius: 100px / 50px; border-radius: 100px / 50px; }
(5)效果顯示: