淘汰赛更改事件处理程序

mic*_*ldd 12 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>
Run Code Online (Sandbox Code Playgroud)

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

    this.selectedLanguage = ko.observable(options.defaultLanguage);
Run Code Online (Sandbox Code Playgroud)

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

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

        app.trigger('language:change', this.selectedLanguage());
    },
Run Code Online (Sandbox Code Playgroud)

问题

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

所以问题是:我能做错什么?我相信这通常是正常的,我必须在某处遗漏某些东西.

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

编辑[求助]

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

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

    <select class="form-control select2"
        data-bind="options:languages,
        optionsText:'label',
        optionsValue:'code',
        value:app.selectedLanguage"></select>
Run Code Online (Sandbox Code Playgroud)

在我的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;
    });
Run Code Online (Sandbox Code Playgroud)

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

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

    app.trigger('language:change', this.selectedLanguage());
},
Run Code Online (Sandbox Code Playgroud)

最好的问候,迈克尔

xdu*_*ine 19

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

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

如果你想像你拥有它一样,知道这一点:在knockout中的事件绑定总是得到对viewModel的引用作为第一个参数,事件数据作为第二个参数,所以你可能必须检查事件以获得如果你这样做,就瞄准并提取价值.原因2不起作用的是您的更改事件在通知淘汰观察结果之前触发,因此您会遇到时间问题.这可能在不同的浏览器中有不同的行为.

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