多个独立视图模型交互(Knockout)

时间:2013-06-11 20:27:13

标签: asp.net mvvm knockout.js typescript

我现在在ASP.Net应用程序中设置了一个视图模型来处理一些数据绑定,它在我的主视图上与Razor模板交互,该模板在多个页面之间共享。我在Razor模板中有一个选择框,它在我当前的视图模型上有一个数据绑定,但是我必须在几个视图模型中复制这个代码以获得相同的功能,我想让我的视图模型的这部分是抽象就像我的模板一样,它是对视图部分的抽象。理想情况下我想要的是类似下面的内容(伪代码):

class ViewModel1{
       function doSomeAjaxStuff(option from select){

       }

      function doSomethingOnSelectorChange(option from select){
           call doSomeAjaxStuff(option from select);

      }
}

class SelectorViewModel{
       function getSelectorValuesFromAjax(){
          //this function will populate the selectors values from an ajax call
       }

       function sendMessageThatSelectorHasChanged(){
           //this will send to the first viewmodel that the selector value has changed

       }
}

我对MVVM架构有点新意,我不确定如何使用knockout进行此操作。有人可以帮助我吗?

1 个答案:

答案 0 :(得分:3)

我不确定这是不是你要问的,但听起来你正在寻找使用Knockout实现类似可重用控件的东西。我们目前采用的一种方法是将自定义绑定处理程序与模板脚本结合使用。例如,给定一些模板:

<script type="text/html" id="selector-template">
    <!-- ko if: isLoading -->
    Loading data...
    <!-- /ko -->
    <!-- ko ifnot: isLoading -->
    <ul data-bind="foreach: items">
        <li data-bind="
            css: { selected: $parent.selectedItem == $data }, 
            template: $parent.itemTemplate, 
            click: selectItem">
        </li>
    </ul>
    <!-- /ko -->
</script>

...和绑定处理程序:

ko.bindingHandlers.selector = {
    init: function(element, valuesAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var bindingValues = valuesAccessor();

        var templateElem = document.createElement('div');
        templateElem.setAttribute('data-bind', 'template: "selector-template"');
        element.appendChild(templateElem);

        var viewModelForControl = new SelectorViewModel(bindingValues);
        var childBindingContext = bindingContext.createChildContext(viewModelForControl);
        ko.applyBindingsToDescendants(childBindingContext, element);
        return { controlsDescendantBindings: true };
    }
};

...您可以像这样实例化自定义控件:

<div data-bind="selector: { 
    itemsUrl: urlForItems, 
    selected: doSomethingOnSelectorChange,
    itemTemplate: 'product-list-item-template'
}"></div>

<script type="text/html" id="product-list-item-template">
    <img data-bind="attr: { src: imageUrl }" />
    <span data-bind="text: description"></span>
</script>