1

我不明白为什么我的视图模块(overlay.screen.view.js)在警报时要求变量未定义(Uncaught TypeError: Cannot call method 'template' of undefined)。路径似乎是正确的,但显然有些事情搞砸了。我做错了什么?提前致谢。

这是我的目录结构:

www
 |-js
   |-app
     consumer.activity.js
     |-views
       overlay.screen.view.js
   |-test
   |-vendor
     |-backbone
     |-fastclick
     |-jquery
     |-sinon
     |-superslides
     |-underscore

在我的 consumer.activity.js 文件中(主要是 main.js):

require.config({

    baseUrl: '../../js',
    paths: {
        root: '..',
        jquery: 'vendor/jquery/jquery.2.0.3.min'
    },
    shim: {
        'underscore': {
            exports: '_'
        },
        'backbone': {
            deps: [
                'underscore',
                'jquery'
            ],
            exports: 'Backbone'
        },
        'fastclick': {
            exports: 'FastClick'
        },
        'phonegap': {
            exports: 'phonegap'
        },
        'cordova': {
            exports: 'cordova'
        },
        'sinon': {
            exports: 'sinon'
        }
    }

});

define(function(require) {

    "use strict";

    var // core libraries
        phonegap                = require('root/phonegap'),
        $                       = require('jquery'),
        _                       = require('vendor/underscore/underscore-1.5.2-min'),
        Backbone                = require('vendor/backbone/backbone-1.1.0-min'),
        FastClick               = require('vendor/fastclick/fastclick-0.6.11-min'),
        appConfig               = require('app/lib/xcelarys.app'),
        ScreenOverlayView       = require('app/views/overlay.screen.view'),
        sinon,
        test,

        // $elements
        $body;

    try {
        // Bootstrap test framework/server
        if (xcelarys.app.environ() === 'DEV' && xcelarys.app.testMode() === 'ON') {
            sinon               = require('test/sinon');
            test                = require('test/xcelarys.test');
        }

        // Perform page config
        FastClick.attach(document.body);    // Make click events fast!

        $body = $('body');

        var screenOverlayView = new ScreenOverlayView( { el: $body } );
        screenOverlayView.render();
        screenOverlayView.show( window.outerHeight, window.outerWidth );
    }
    catch(e) {
        console.log(e);
    }

});

这是视图模块,overlay.screen.view.js:

define( function( require ) {

    "use strict";

    var  $               = require('jquery'),
         _               = require('../../vendor/underscore/underscore-1.5.2-min'),
         Backbone        = require('../../vendor/backbone/backbone-1.1.0-min'),
         tmpl            = require('text!app/tmpl/overlayscreen.html'),
         template        = _.template(tmpl);  // // Uncaught TypeError: Cannot call method 'template' of undefined .

    alert($);
    alert(_);
    alert(Backbone);
    alert(template());

    return Backbone.View.extend({

        render: function() {

            this.$el.append(template());
            return this;

        },

        show: function( heightInPixels, widthInPixels ) {

            this.$('#overlayscreen').css('height', heightInPixels);
            this.$('#overlayscreen').css('width', widthInPixels);
            this.$('#overlayscreen').removeClass('hide');

        },

        hide: function() {

            this.$el.addClass('hide');

        }

    });

});

更新

Seddass 在下面的帖子引导我找到以下解决方案。本质上,我需要更新 require.config() 路径,以便垫片按预期工作。这是代码:

require.config({
    baseUrl: '../../js',
    paths: {
        root: '..',
        jquery: 'vendor/jquery/jquery.2.0.3.min',
        underscore: 'vendor/underscore/underscore-1.5.2-min',
        backbone: 'vendor/backbone/backbone-1.1.0-min',
        test: 'test'
    },

    shim: {
        'jquery': {
            exports: '$'
        },
        'underscore': {
            exports: '_'
        },
        'backbone': {
            deps: [
                'underscore',
                'jquery'
            ],
            exports: 'Backbone'
        },
        'fastclick': {
            exports: 'FastClick'
        },
        'phonegap': {
            exports: 'phonegap'
        },
        'cordova': {
            exports: 'cordova'
        },
        'sinon': {
            exports: 'sinon'
        }
    }
});

require([
    'root/phonegap',
    'jquery',
    'underscore',
    'backbone',
    'vendor/fastclick/fastclick-0.6.11-min',
    'app/lib/xcelarys.app',

    // Views
    'app/views/overlay.screen.view',
    'app/views/global.header.1.view',

    // Models
    'app/models/global.header.1.models'
    ],
    function(
        phonegap,
        $,
        _,
        Backbone,
        FastClick,
        appConfig,
        ScreenOverlayView,
        GlobalHeader1,
        GlobalHeader1Model
    ) {
        "use strict";
        // code
    }
});

现在我可以访问我模块中的库。

define( function( require ) {
    "use strict";
    var  $               = require('jquery'),
         _               = require('underscore'),
         Backbone        = require('backbone'),
         tmpl            = require('text!app/tmpl/overlayscreen.html'),
         template        = _.template(tmpl);

    alert('overlay.screen#jquery = ' + $);
    alert('overlay.screen#underscore = ' + _);
    alert('overlay.screen#backbone = ' + Backbone);
    alert('overlay.screen#template' + template());

    // Code here!
});
4

2 回答 2

2

我猜您的 Underscore.js 版本未启用 AMD,因此您在配置中使用了 shim。但我相信,当调用

require('../../vendor/underscore/underscore-1.5.2-min');

您的垫片无法识别您正在调用“下划线”来启用“_”的导出。您是否尝试在路径中设置下划线,在 shim 设置中以及稍后要求它使用相同的路径?

换句话说:

require.config({
    ...
    paths: {
        'underscore' : '../../vendor/underscore/underscore-1.5.2-min',
        ....
    },
    shim: {
        'underscore' : {
             exports: '_'
        }
    }
});

在您看来(或在任何 AMD js 文件中):

var _ = require('underscore'); 

应该管用。

于 2013-11-05T19:57:26.323 回答
0

问题是到时候,它会执行

template        = _.template(tmpl);

underscorejs 可能没有完全加载。在异步模块定义(AMD)中有“异步”的意思。您需要将代码重组为如下所示的内容以使其工作:

require(['underscore', 'text!app/tmpl/overlayscreen.html'], function (_, tmpl) {
    template        = _.template(tmpl);
    console.log (template);

});

您还可以查看此处的示例。

更新

在此处使用 jsfiddle 模拟您的情况。由于您在配置对象中定义了所有模块,因此您可以在“sugar”版本中使用模块名称,如下所示,它应该可以工作。

var  $               = require('jquery'),
     _               = require('underscore'),
    Backbone         = require('backbone');
于 2013-11-05T16:54:13.960 回答