在Knockout.JS中查看模型更新后调用视图函数

时间:2012-04-11 19:57:47

标签: knockout.js

我使用优秀的Cycle.js插件创建了一个简单的内容旋转器,这从我的Knockout.JS视图模型属性(在本例中为appViewModel.mediaPlayer)获取内容:

e.g。

  var testData = [{ url: "media/1.png" }, { url: "media/2.jpg"}];

    var appViewModel =
    {
        mediaPlayer: new ko.observableArray(testData)
    };

    ko.applyBindings(appViewModel);

这在使用JQuery Tmpl的视图中呈现,例如

 <script id="mediaPlayerTemplate" type="text/template">
        <img src=${url} />
    </script>

<div class="adContainer" data-bind="template: {name: 'mediaPlayerTemplate', foreach: mediaPlayer}">
    </div>

要开始图像转换,我只需将Cycle插件方法称为“循环”:

 $('.adContainer').cycle({
            fx: 'fade',
            timeout: 1000,
            speed: 500
        });

这很好用,但是当我更新我的视图模型媒体播放器内容时,循环插件停止工作......这不是问题,因为对循环()的简单调用将再次启动它。

但是,我的问题是,调用cycle()更新视图的最佳位置在哪里?我想我可以订阅mediaPlayer更改,只需在需要时调用该方法,但这意味着我必须将JQuery元素/视图逻辑放在View模型中,感觉不对(也许我试图太纯粹了!)

简而言之,如何在视图模型中触发视图中的函数而视图模型不知道视图函数?在Silverlight / WPF中,这可能是XAML中的触发器,但我不确定如何使用Knockout.JS实现相同的分离

1 个答案:

答案 0 :(得分:3)

我认为使用绑定处理程序更好,这也可以让你在重新呈现内容时正确处理插件。

你的例子(它将在5秒后改变周期):

http://jsfiddle.net/nickolsky/uXDUA/2/

<强> HTML:

<script id="mediaPlayerTemplate" type="text/template">
        <img src=${url} />
    </script>

<div data-bind="template: {name: 'mediaPlayerTemplate', foreach: mediaPlayer}, cycle: { fx: 'fade', timeout: 1000, speed: 500 }, cycleLinked: mediaPlayer">
    </div>

<强> JAVASCRIPT:

ko.bindingHandlers.cycle = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        $element = $(element);
        var options = ko.utils.unwrapObservable(valueAccessor()) || {};
        //console.log('cycle_init');
        var _starting = false;

        var _cycle = function() {
            if(_starting) return;
            _starting = true;
            //console.log('cycle_create');
            $element.hide();
            setTimeout(function() { $(element).cycle(options); $element.show(); _starting = false; }, 0);
        };

        var subscription = allBindingsAccessor().cycleLinked.subscribe(_cycle);
        //handle disposal
        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            //console.log('cycle_destroy');
            $element.cycle("destroy");
            subscription.dispose();
        });
        _cycle();

    }
};


var testData = [{
    url: "http://cloud.github.com/downloads/malsup/cycle/beach1.jpg"},
{
    url: "http://cloud.github.com/downloads/malsup/cycle/beach2.jpg"}];

var appViewModel = {
    mediaPlayer: new ko.observableArray(testData)
};

ko.applyBindings(appViewModel);

setTimeout(function() {
 appViewModel.mediaPlayer.push({url: "http://cloud.github.com/downloads/malsup/cycle/beach3.jpg"});
appViewModel.mediaPlayer.push({url: "http://cloud.github.com/downloads/malsup/cycle/beach4.jpg"});
    }, 5000);​