Require.js模块路径范围问题

时间:2013-11-05 15:53:04

标签: javascript backbone.js module requirejs underscore.js

我不明白为什么我的视图模块(overlay.screen.view.js)要求变量未定义(Uncaught TypeError:无法调用未定义的方法'模板')。路径似乎是正确的,但显然有些东西搞砸了。我做错了什么?提前谢谢。

这是我的目录结构:

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
    }
});

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

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!
});

2 个答案:

答案 0 :(得分:2)

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

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

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

换句话说:

require.config({
    ...
    paths: {
        'underscore' : '../../vendor/underscore/underscore-1.5.2-min',
        ....
    },
    shim: {
        'underscore' : {
             exports: '_'
        }
    }
});
在您的视图中(或在任何AMD js文件中)

var _ = require('underscore'); 

应该有效。

答案 1 :(得分:0)

问题在于,到时候,它会被执行

template        = _.template(tmpl);

underscorejs可能未完全加载。异步模块定义(AMD)中存在“异步”的含义。您需要将代码重构为类似下面的代码才能使其正常工作:

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

});

您还可以查看here中的示例。

<强>更新

使用here中的jsfiddle模拟您的情况。 既然您已经在config对象中定义了所有模块,那么您可以使用'sugar'版本中的模块名称,如下所示,它应该可以工作。

var  $               = require('jquery'),
     _               = require('underscore'),
    Backbone         = require('backbone');