KnockOutJS-단일 뷰의 다중 ViewModel


201

하나의 ViewModel로 각보기를 처리하기에는 응용 프로그램이 너무 커지고 있다고 생각합니다.

그래서 여러 ViewModel을 만들어 단일 View에로드하는 것이 얼마나 어려운지 궁금합니다. 또한 X ViewModel 데이터를 Y ViewModel 데이터로 전달할 수 있어야 개별 ViewModel이 서로 통신하거나 최소한 서로를 인식 할 수 있어야합니다.

예를 들어 <select>드롭 다운이 있습니다. 선택 드롭 다운에는 선택된 상태가있어 선택한 항목의 ID를 <select>별도의 ViewModel에서 다른 Ajax 호출 로 전달할 수 있습니다 ....

단일 View에서 수많은 ViewModel을 다루는 데 대한 모든 점은 높이 평가했습니다. :)


12
이 질문에 도착한 사람은 허용 된 답변을지나 스크롤하십시오. 녹아웃은 이제 여러 바인딩 컨텍스트를 지원합니다 . 거인이 필요하지 않습니다 masterVM.
캐리 켄달

답변:


150

모두 동일한 페이지에 있어야하는 경우이를 수행하는 한 가지 쉬운 방법은 다른 뷰 모델의 배열 (또는 속성 목록)을 포함하는 마스터 뷰 모델을 갖는 것입니다.

masterVM = {
    vmA : new VmA(),
    vmB : new VmB(),
    vmC : new VmC(),
}

그런 다음 masterVM필요한 경우 페이지 자체에 대한 다른 속성을 가질 수 있습니다. 이 상황에서을 통해 릴레이 masterVM하거나 $parent/ $rootin 바인딩 또는 다른 사용자 정의 옵션을 사용할 수 있으므로 뷰 모델 간의 통신은 어렵지 않습니다 .


2
따라서 data-bind = "text : masterVM.vmA"와 같은 작업을 수행 할 수 있습니다. DOM 요소가 연결된 상태에서 ko.applyBindings를 계속 사용할 수 있다고 가정합니다. data-bind = "$ parent.masterVm"도 가능하다는 뜻입니까?
CLiown

12
@CLiown 바인딩을 사용할 수 with:있으므로 반복하지 않습니다
AlfeG

4
@CLiown 예, masterVM에 바인딩하면 그렇게 할 수 있습니다. "with"바인딩을 사용하여 하위 뷰 모델로 다이빙 할 때 점 구문을 피할 수 있습니다.
John Papa

1
나는이 접근법이 매우 제한적인 것이라고 생각합니다 ... 이제 ASP.Net MVC4를 사용하고 있습니다. 조건부 렌더링으로 인해이 방법을 사용하는 것은 실제로 어려울 것입니다.
bhuvin

1
<!-ko stopBinding : true->를 사용하는 @bhuvin은 다중 뷰 모델 및 부분 뷰 섹션에 도움이됩니다. 자세한 내용은 knockmeout.net/2012/05/quick-tip-skip-binding.html 을 참조하십시오.
Micaël Félix

285

녹아웃은 이제 여러 모델 바인딩을 지원합니다. 이 ko.applyBindings()메소드는 선택적 매개 변수 (요소 및 바인딩이 활성화 될 하위 항목)를 사용합니다.

예를 들면 다음과 같습니다.

ko.applyBindings(myViewModel, document.getElementById('someElementId'))

이렇게하면 ID someElementId및 해당 하위 항목이있는 요소로 활성화가 제한 됩니다.

자세한 내용은 설명서 를 참조하십시오.


72
jQuery 선택기를 사용하려면 다음 [0]과 같이 jQuery 객체 대신 실제 DOM 요소를 지정 하도록 추가 해야합니다.ko.applyBindings(myViewModel, $('#someElementId')[0])
MrBoJangles

3
이것이 정답입니다. 현재 허용 된 답변과 같은 마스터 객체를 계속 사용하고 개별 뷰 모델을 페이지의 해당 요소에 바인딩 할 수 있습니다. 이렇게하면 성능이 저하되고 데이터 바인딩에 필요한 범위가 제한됩니다.
Kevin Heidt

이 접근 방식으로 viewModel을 서로 통신 할 수 있습니까? 즉, TaskVM과 NoteVM이 있습니다. 작업에는 메모가있을 수 있습니다. 따라서 내 TaskVM에는 ObservableArray, 즉 유형이 TaskVM 인 메모가 있어야합니다. 그런 경우에 대한 예를 말씀해 주시겠습니까?
ahmet

새로운 질문으로 VM 간의 통신에 대해 문의하는 것이 가장 좋습니다.
Richard Nalezynski 2016

21

이것은 단일 뷰에서 많은 ViewModel이있는 매우 큰 프로젝트를 완료 한 후의 대답입니다.

HTML보기

    <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
    <div id="container1">
        <ul>
            <li >Container1 item</li>
            <!-- ko foreach: myItems -->
            <li>Item <span data-bind="text: $data"></span></li>
            <!-- /ko -->
        </ul>
    </div>

    <div id="container2">
        <ul>
            <li >Container2 item</li>
            <!-- ko foreach: myItems -->
                <li>Item <span data-bind="text: $data"></span></li>
            <!-- /ko -->
        </ul>
    </div>

    <script src="js/jquery-1.11.1.js"></script>
    <script src="js/knockout-3.0.0.js"></script>
    <script src="js/DataFunction.js"></script>
    <script src="js/Container1ViewModel.js"></script>
    <script src="js/Container2ViewModel.js"></script>

</body>
</html>

이보기를 위해 두 개의 별도 자바 스크립트 파일에서 id = container1 및 id = container2에 대한 두 가지보기 모델을 만들고 있습니다.

Container1ViewModel.js

function Container1ViewModel()
{
    var self = this;
    self.myItems = ko.observableArray();
    self.myItems.push("ABC");
    self.myItems.push("CDE");

} 

Container2ViewModel.js

function Container2ViewModel() {
    var self = this;
    self.myItems = ko.observableArray();
    self.myItems.push("XYZ");
    self.myItems.push("PQR");

}

그런 다음이 두 개의 뷰 모델이 DataFunction.js에 별도의 뷰 모델로 등록 된 후

var container1VM;
var container2VM;

$(document).ready(function() {

    if ($.isEmptyObject(container1VM)) {
        container1VM = new Container1ViewModel();
        ko.applyBindings(container1VM, document.getElementById("container1"));
    }

    if ($.isEmptyObject(container2VM)) {
        container2VM = new Container2ViewModel();
        ko.applyBindings(container2VM, document.getElementById("container2"));
    }
});

이와 같이 별도의 div에 여러 개의 뷰 모델을 추가 할 수 있습니다. 그러나 등록 된 div 안에 div에 대해 별도의 뷰 모델을 만들지 마십시오.


DOM의 개별 요소 대신 다른 종류의 뷰 모델로 할 수 있습니까?
UserEsp

4

녹아웃 JS에 대한 MultiModels에게 플러그인을 확인 - https://github.com/sergun/Knockout-MultiModels


6
이것이 ko.applyBindings (viewModel, document.getElementById ( "divName"))보다 어떤 장점이 있습니까? 그것은 단지 구문 설탕 아닌가요?
Paolo del Mundo

1
@Paolo del Mundo 또한 LiveQuery 플러그인에 대한 의존성을 추가합니다.
Lars Gyrup Brink Nielsen 님이

@PaolodelMundo 플러그인의 목적은 뷰 모델 세트를 비례 적으로 사용할 수 있도록하는 것입니다
Sergey Zwezdin

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.