2013-05-14 89 views
1

我有3條路線:items/one,items/two和items/three,它們都指向'items'vm/view。Durandal:Multiple Routes,One ViewModel/View

在items.js

激活功能,我檢查的網址,並此基礎上,我改變了一個過濾器:

function activate(r) { 
     switch (r.routeInfo.url) { 
      case 'items/one': vm.filterType(1); break; 
      case 'items/two': vm.filterType(2); break; 
      case 'items/three': vm.filterType(3); break; 
     } 
     return init(); //returns a promise 
    } 

項目視圖與按鈕的菜單一,二,和三個。 每個按鈕鏈接到一個這樣的動作:

function clickOne() { 
    router.navigateTo('#/items/one'); 
} 
function clickTwo() { 
    router.navigateTo('#/items/two'); 
}  
function clickThree() { 
    router.navigateTo('#/items/three'); 
} 

這一切工作,我得到的觀點正確的過濾器。但是,我注意到,如果我在'one',然後轉到'two',那麼ko-bound變量會'實時'更新,也就是說,當它們在變化時,並且在激活之前承諾解決,這導致轉換髮生兩次(當數據被抓取,並在激活函數返回後)。

這隻發生在這種情況下,其中view和viewmodel與前一個相同。我知道這是一種特殊情況,路由器可能正在用areSameItem = true處理新路由的加載。我可以將虛擬機/視圖分成三部分,並嘗試從基本模型繼承,但我希望獲得更簡單的解決方案。

+0

它調用你的'activate'函數嗎? 'filterType()'返回一個承諾? – Tyrsius 2013-05-14 03:11:53

+0

當路由器導航到視圖/虛擬機時,激活函數被框架(Durandal)自動調用。 filterType只是一個帶有整數值的ko.observable。 – 2013-05-14 03:27:50

+0

好的,所以當你設置'filterType'時會觸發一個動畫?這是來自訂戶嗎?您可能希望將其作爲init()的一部分,以便它返回的承諾適用於這兩種情況。 – Tyrsius 2013-05-14 03:44:20

回答

1

我能夠通過使用包含分區項目ko.cleanNode()導航之前簡單地移除KO綁定解決問題。

+0

很高興知道。我必須在下次碰到它時嘗試。 – RainerAtSpirit 2013-05-15 15:01:26

+0

你在哪裏叫cleanNode?你是否需要重新添加綁定? – Ely 2013-06-06 04:21:23

+0

@Ely我在'router.navigateTo(...)'之前調用了它,例如,如果我的div被稱爲items,我會調用'var items = $('#items')[0]; ko.cleanNode(項目);' – 2013-06-07 08:04:35

0

假設在您的父視圖中,您已參考router.activeItem並使用transition(例如,

<!--ko compose: {model: router.activeItem, 
    afterCompose: router.afterCompose, 
    transition: 'entrance'} --> 
<!--/ko--> 

然後入口過渡發生在您設置的每條路線上以過濾當前視圖。

但是這種轉換應該只在第一次訪問時發生,並且從那一刻起只有視圖應該使用過濾的數據進行更新。一種方法是設置一個可觀察的filterType並使用filterType.subscribe用skip參數調用router.navigateTo。沿線

東西:

var filterType = ko.observable(); 

filterType.subscribe(function (val) { 
    // Create an entry in the history but don't activate the new route to prevent transition 
    // router plugin expects this without leading '/' dash. 
    router.navigateTo(location.pathname.substring(1) + '#items/' + filterType(), 'skip'); 
    activate(); 
}); 

請注意路由器插件預計skipRouteUrl,而不會導致/斜線比較context.path。 https://github.com/BlueSpire/Durandal/blob/master/App/durandal/plugins/router.js#L402

您的體驗可能會有所不同。

末爲了支持深層鏈接在activate

function activate(routerdata) { 
    // deep linking 
    if (routerdata && routerdata.filterType && (routerdata.filterType !== filterType())) { 
     filterType(routerdata.filterType); 
    } 

    return promise; 
}; 
+0

這是有效的,但正如你所說,現在過渡已經結束,與其他應用程序相比,這給人一種粗糙的體驗。有沒有辦法添加過渡效果(即使它純粹通過jQuery)?我嘗試在KO模板中使用beforeRemove和afterAdd綁定,但這些似乎不起作用。 – 2013-05-14 09:05:03

+0

。例如'var isFetching = ko.observable(false)',你可以在'subscribe'中將它設置爲'true'。在激活更改返回init()到$ .when(init())。然後(function(){self.isFetching(false)}); – RainerAtSpirit 2013-05-14 12:37:17

+0

下一次嘗試: 您可能會考慮將'var isFetching = ko.observable(false)'添加到您的VM。通過在'subscribe'中將其設置爲'true',您可以確定動畫的起點。在'activate'中,而不是將promise改回'$ .when(promise).then(function(){...});'會讓你將它設置回false。 – RainerAtSpirit 2013-05-14 12:52:43