2014-11-07 3 views
4

나는이 사건을 처리하기 위해 제공하는 가능성 사이에 손실 오전 : - HTML을 아약스 를 통해로드 Sammy.js와녹아웃 SPA 아약스로드 템플릿

  • 녹아웃
  • SPA : 이제 우리는 다음과 같은 제약이 가정 해 봅시다

내 페이지 : 현재

+-------------------------------+ 
| #navigation     | 
+---------+---------------------+ 
| #sidebar| #content   | 
|   |      | 
|   |      | 
|   |      | 
+---------+---------------------+ 

, 나는 D를 처리 한 appViewModel이 모든 웹 사이트의 요소에 대한 ata-bind : #navigation 및 #sidebar. 이 appViewModel은 내 웹 사이트의 모든 페이지에서 사용 가능합니다.

이제 #content가 Ajax 호출을 통해로드 된 DOM 조각이라고 가정 해 보겠습니다. 사용자가 #navigation 또는 #sidebar 내부의 링크를 클릭 할 때마다 Sammy.js가이를 가로 채고 #content를 업데이트합니다. 문제는 #content 내의 새로운 DOM에 데이터 바인딩 자체가 있다는 것입니다.

1) 우선, I는 #content에 HTML 데이터 바인딩을 사용한다 replaceWith (위) 또는 템플릿을 얻을 지정 함수와 결합 템플릿? (http://knockoutjs.com/documentation/template-binding.html#note-5-dynamically-choosing-which-template-is-used)? 여기에서 가장 좋은 방법은 무엇입니까?

2) 문서 나 다른 곳에서 Sammy가 appViewModel 내에 있어야합니까?

3) updateView 메소드가 완료되면 어떻게 새 DOM을 바인딩하겠습니까? 아래처럼? ko.applyBindings가 이미 두 번째 인수없이 호출 되었기 때문에 일부 DOM을 다시 바인딩 할 위험이 있습니까?

ko.applyBindings(new routeSpecificViewModel() , document.getElementById("content")); 

귀하의 도움에 감사드립니다.

+0

, 나는 당신이 이제까지 해결책을 마련했다면 물어보고 싶은게 년 이상 오래? 나는 똑같은 딜레마에 직면하고있다. – mls3590712

+0

이전 질문 :-) 나는 knockout AMD with requireJs와 flatiron/director를 라우터로 사용하는 것을 끝내었다. 이것은 매력처럼 작동합니다. 이 스택을 사용하면 이러한 질문을 피할 수있는 제약 조건이 생깁니다. – Xavier13

답변

0

하나의 간단한 해결책은 페이지의보기 모델을 관찰 가능하게 만들고 ondemand를로드하는 것입니다. ko.applyBindings가 호출되었는지 변수를 사용하여 기록하십시오. 녹아웃 - 스파 프레임 워크에서 예 :

/*! knockout-spa (https://github.com/onlyurei/knockout-spa) * Copyright 2015-2016 Cheng Fan * MIT Licensed (https://raw.githubusercontent.com/onlyurei/knockout-spa/master/LICENSE) */ 

define(['app/shared/root-bindings', 'framework/page-disposer', 'ko', 'sugar'], function (
    RootBindings, PageDisposer, ko) { 

    var initialRun = true; 

    var Page = { 
    init: function (name, data, controller, path) { 
     Page.loading(false); 

     name = name.toLowerCase(); 

     if ((Page.page().name == name) && (Page.page().data == data)) { // if the requested page is the same page, immediately call controller without going further 
     if (controller) { 
      controller(data); 
     } 

     document.title = Page.title(); 

     if (Page.initExtra) { 
      Page.initExtra(name, data, controller); 
     } 

     return data; 
     } 

     var autoDispose = (Page.page().data.dispose && Page.page().data.dispose(Page)) || true; // if the requested page is not the same page, dispose current page first before swap to the new page 
     if (autoDispose !== false) { 
     // auto-dispose page's exposed observables and primitive properties to initial values. if not desired, return 
     // false in dispose function to suppress auto-disposal for all public properties of the page, or make the 
     // particular properties private 
     PageDisposer.dispose(Page.page().data); 
     } 

     PageDisposer.init(data); //store initial observable and primitive properties values of the page 
     var initialized = (data.init && data.init(Page)) || true; // init view model and call controller (optional) before template is swapped-in 
     if (initialized === false) { 
     return false; // stop initialization if page's init function return false (access control, etc.) 
     } 
     if (controller) { 
     controller(data); 
     } 

     Page.pageClass([name, ('ontouchstart' in document.documentElement) ? 'touch' : 'no-touch'].join(' ')); 
     Page.page({ 
     name: name, 
     data: data, 
     path: path 
     }); // to test if template finished rendering, use afterRender binding in the template binding 

     document.title = Page.title(); 

     if (Page.initExtra) { 
     Page.initExtra(name, data, controller); // useful for common init tasks for all pages such as anaylitics page view tracking, can be set in RootBindings 
     } 

     if (initialRun) { 
     ko.applyBindings(Page, document.getElementsByTagName('html')[0]); // apply binding at root node to be able to bind to anywhere 
     initialRun = false; 
     } 

     return data; 
    }, 
    page: ko.observable({ 
     name: '', // name of the page - auto-set by the framework, no need to worry 
     data: { 
     init: function() {}, // preparation before the page's template is rendered, such as checking access control, init/instantiate modules used by the page, etc. 
     dispose: function() {} // properly dispose the page to prevent memory leaks and UI leftovers (important for SPA since page doesn't refresh between page views) - remove DOM element event listeners, dispose knockout manual subscriptions, etc. 
     } 
    }), 
    pageClass: ko.observable(''), 
    loading: ko.observable(false), 
    title: function() { 
     return Page.page().name.titleize(); // override in RootBindings as needed 
    } 
    }; 

    Object.merge(Page, RootBindings); // additional root bindings as needed by the app 

    return Page; 

}); 

미니하지만, 마네의 상단에 내장 본격적인 SPA 프레임 워크, 이사, jQuery를, 설탕 요구합니다.

라이브 데모 https://github.com/onlyurei/knockout-spa이 이후 https://knockout-spa.mybluemix.net