淘汰赛更改事件处理程序

时间:2014-03-21 13:03:59

标签: javascript knockout.js durandal

我花了好几个小时试图让我的durandal / knockout应用程序中的一个简单的事件调用正常工作。

上下文

我有一个用户可以从选择框中选择的语言列表:

    <select class="form-control select2"
        data-bind="event: { change: app.languageChanged }, options:languages,
        optionsText:'label',
        optionsValue:'code',
        value:app.selectedLanguage"></select>

属性app.selectedLanguage是一个ko.observable。我知道这是有效的,因为正确的项目是预选的。

    this.selectedLanguage = ko.observable(options.defaultLanguage);

我还有一个事件处理程序,它监听该选择框的更改,以便我可以向应用程序的其他需要通知的部分发送消息:

    languageChanged : function(data, event) {
        console.log(data);
        console.log(event);
        console.log(this.selectedLanguage());

        app.trigger('language:change', this.selectedLanguage());
    },

问题

  1. 第一个参数'data'不包含所选项目,而是包含所有项目(实际上,它似乎是完整的当前视图模型)。
  2. 如果1.不起作用,那么它至少可以从可观察的“selectedLanguage”中获取新值。不幸的是,似乎总是有旧的价值。所以每当我更改selectbox选项时,我总是得到之前选择的值。
  3. 问题

    所以问题是:我可能做错了什么?我确信这通常可以正常工作,我必须在某处遗漏某些东西。

    我以为我终于明白了淘汰赛是如何运作的,但现在我遇到了下一个问题。如果有人能帮助我,我将非常感激。

    编辑[已解决]

    感谢xdumaine,这是(好的和简单的)解决方案:

    在我的html模板中,我删除了更改事件:

        <select class="form-control select2"
            data-bind="options:languages,
            optionsText:'label',
            optionsValue:'code',
            value:app.selectedLanguage"></select>
    

    在我的App视图模型中(我需要随处可见),我现在订阅了ko.observable而不是监听事件处理程序:

        define([ 'durandal/app', 'underscore', 'knockout', 'myapp/myapp' ], function(app, _, ko, myapp) {
    
            "use strict";
    
            function App(options) {
    
                if (!(this instanceof App)) {
                    throw new TypeError("App constructor cannot be called as a function.");
                }
    
                this.options = options || {};
    
                // Set the initial language.
                this.selectedLanguage = ko.observable(options.defaultLanguage);
                        // *** Subscribes to the observable ***
                this.selectedLanguage.subscribe(function(newValue) {
                    console.log(newValue);
                    app.trigger('language:change', newValue);
                });
    
                _.bindAll(this, 'getSelectedLanguage');
            }
    
            App.prototype = {
                constructor : App,
                getSelectedLanguage : function() {
                    return this.selectedLanguage();
                }
            }
    
            return App;
        });
    

    此代码已被删除,不再需要:

    languageChanged : function(data, event) {
        console.log(data);
        console.log(event);
        console.log(this.selectedLanguage());
    
        app.trigger('language:change', this.selectedLanguage());
    },
    

    祝你好运, 迈克尔

1 个答案:

答案 0 :(得分:18)

为什么要绑定到select change事件而不是只订阅selectedLanguage?

var self = this;
self.selectedLanguage = ko.observable();
self.selectedLangauge.subscribe(function(newValue) {
    console.log(newValue);
    app.trigger('language:change', newValue);
});

如果你想这样做,请知道:敲门时的事件绑定总是得到对viewModel的引用作为第一个参数,事件数据作为第二个参数,所以你可能需要检查事件获取目标并提取值,如果你这样做的话。原因2不起作用的是您的更改事件在通知淘汰观察结果之前触发,因此您会遇到时间问题。这可能在不同的浏览器中有不同的行为。

我建议尽可能坚持使用可观察的订阅,而不是使用DOM事件。