【问题标题】:jquery and requirejs and knockout; reference requirejs object from within itselfjquery 和 requirejs 以及淘汰赛;从自身内部引用 requirejs 对象
【发布时间】:2012-11-18 15:21:07
【问题描述】:

我们使用 jquery 和 requirejs 来创建一个像这样的“viewmodel”:

define('vm.inkoopfactuurAanleveren',
['jquery', 'underscore', 'ko', 'datacontext', 'router', 'messenger', 'config', 'store'],
function ($, _, ko, datacontext, router, messenger, config, store) {
    var
        isBusy = false,
        isRefreshing = false,
        inkoopFactuur = { factuurNummer: ko.observable("AAA") },           
        activate = function (routeData, callback) {
            messenger.publish.viewModelActivated({ canleaveCallback: canLeave });
            getNewInkoopFactuurAanleveren(callback);              
            var restricteduploader = new qq.FineUploader({                    
                element: $('#restricted-fine-uploader')[0],
                request: {
                    endpoint: 'api/InkoopFactuurAanleveren',
                    forceMultipart: true
                },
                multiple: false,                 
                failedUploadTextDisplay: {
                    mode: 'custom',
                    maxChars: 250,
                    responseProperty: 'error',
                    enableTooltip: true
                },
                text: {
                    uploadButton: 'Click or Drop'
                },
                showMessage: function (message) {                        
                    $('#restricted-fine-uploader').append('<div class="alert alert-error">' + message + '</div>');
                },
                debug: true,

                callbacks: {
                    onComplete: function (id, fileName, responseJSON) {
                        var response = responseJSON;
                    },
                }
            });
        },

       invokeFunctionIfExists = function (callback) {
           if (_.isFunction(callback)) {
               callback();
           }
       },

        loaded = function (factuur) {
            inkoopFactuur = factuur;
            var ids = config.viewIds;
            ko.applyBindings(this, getView(ids.inkoopfactuurAanleveren)); /*<----- THIS = OUT OF SCOPE!*/                /
        },

        bind = function () { },

        saved = function (success) {
            var s = success;
        },

        saveCmd = ko.asyncCommand({
            execute: function (complete) {
                $.when(datacontext.saveNewInkoopFactuurAanleveren(inkoopFactuur))
                        .then(saved).always(complete);
                return;
            },
            canExecute: function (isExecuting) {
                return true;
            }
        }),

        getView = function (viewName) {
            return $(viewName).get(0);
        },

        getNewInkoopFactuurAanleveren = function (callback) {
            if (!isRefreshing) {
                isRefreshing = true;                    
                $.when(datacontext.getNewInkoopFactuurAanleveren(dataOptions(true))).then(loaded).always(invokeFunctionIfExists(callback));
                isRefreshing = false;
            }

        },

        dataOptions = function (force) {
            return {
                results: inkoopFactuur,
                // filter: sessionFilter,
                //sortFunction: sort.sessionSort,
                forceRefresh: force
            };
        },

        canLeave = function () {
            return true;
        },            

        forceRefreshCmd = ko.asyncCommand({
            execute: function (complete) {
                //$.when(datacontext.sessions.getSessionsAndAttendance(dataOptions(true)))
                //    .always(complete);
                complete;
            }
        }),                        

        init = function () {
           // activate();
            // Bind jQuery delegated events
            //eventDelegates.sessionsListItem(gotoDetails);
            //eventDelegates.sessionsFavorite(saveFavorite);

            // Subscribe to specific changes of observables
            //addFilterSubscriptions();
        };

        init();

    return {
        activate: activate,
        canLeave: canLeave,
        inkoopFactuur: inkoopFactuur,
        saveCmd: saveCmd,
        forceRefreshCmd: forceRefreshCmd,
        bind: bind,
        invokeFunctionIfExists: invokeFunctionIfExists                  
    };
});

在'loaded'方法中的ko.applyBindings(this, getView(ids.inkoopfactuurAanleveren));线上 “this”关键字不引用“viewmodel”对象。 “self”关键字似乎是指在多个“viewmodel”上找到的方法的组合。 saveCmd 属性是通过敲除绑定的,但由于找不到它而报错。

ko.applyBindings 如何获得对视图模型的正确引用? 换句话说,我们需要用什么来替换applyBindings中的'this'关键字。

我想你可以“要求”requirejs 给我们带有标识符“vm.inkoopfactuurAanleveren”的 ealiers 实例化对象,但我不知道怎么做。

【问题讨论】:

    标签: jquery knockout.js requirejs


    【解决方案1】:

    只需在function ($, _, ko, datacontext, router, messenger, config, store) { 行之后使用此行

    var me = this;
    

    然后在你需要参考的地方使用我

    *请注意,这可能不是最好的方法,但这就是我不这样做的方式-cntrl下的所有内容

    【讨论】:

    • 我也会快速尝试一下,作为快速修复,这似乎是最简单的方法,但是,这并不是真正的长期解决方案。
    • 这不起作用,此时这已经超出范围并且不引用视图模型。
    【解决方案2】:

    您遇到的问题不是来自 RequireJS,而是来自您创建视图模型的方式以及您没有注意函数中的“this”是什么这一事实。

    通过阅读您的代码,我可以告诉您,您加载的方法中的“this”是一个 jQuery Deferred 对象,看起来像这样
    Object,
    always: function (){ ... },
    done: function (){ ... },
    fail: function (){ ... },

    这个简短的教程将让您了解问题所在。 http://dailyjs.com/2012/06/18/js101-this/

    要使这项工作正常进行,只要您像 viewModel.activate() 那样调用激活,请在您的 getNewInkoopFactuurAanleveren 函数中将 .then(loaded) 更改为 .then($.proxy(loaded, this))。这应该使 loaded 函数中的 this 成为 viewmodel 对象。

    但是,您应该决定一种更好的方法来在您的应用程序中构建可重用的模块或类,并在这些 RequireJS 定义方法中创建构造函数将是一个好的开始。

    define([ "jquery" ], function ($) {  
        var User = function (username, password) {  
            this.username = username;  
            this.password = password;  
            this.isActive = false;
        }  
    
        User.prototype.activate = function () {  
            this.isActive = true;  
        };  
    
        return User;  
    }
    

    请注意,RequireJS 只会调用此方法一次,这就是为什么最好创建一个构造函数,然后在需要该类型的新对象时使用它。

    var user = new User("user1", "pass");  
    user.activate();  
    

    在此处查看有关如何创建简单类的一些示例。 http://weblogs.asp.net/dwahlin/archive/2011/12/19/using-the-javascript-prototype-property-to-structure-and-extend-code.aspx.

    【讨论】:

    • 我将深入研究并尝试找出如何改变事情。我们遵循了 John Papa 的 codecamper SPA 示例,并尝试使用它以类似的方式构建我们自己的应用程序,因此更改所有代码可能有些困难;)感谢您的广泛回答。
    • 用 .then($.proxy(loaded, this)) 更改代码还不起作用,我认为这是因为当 viewmodel 上的 activate 方法时 this 变量已经超出范围正在被调用。
    • 是的,你是对的。第 10 行的 getNewInkoopFactuurAanleveren(callback); 应该是 this.getNewInkoopFactuurAanleveren(callback);。我错过了。
    猜你喜欢
    • 2013-08-05
    • 2013-10-21
    • 1970-01-01
    • 2015-04-29
    • 2014-08-08
    • 2012-11-09
    • 1970-01-01
    • 2015-09-16
    • 2014-01-30
    相关资源
    最近更新 更多