2015-10-01 46 views
0

当使用requirejs加载handlebarjs时,我得到一条ReferenceError: Handlebars is not defined消息。与RequireJS一起使用手柄,ReferenceError:手柄未定义

这是我在app.js配置文件

requirejs.config({ 
    'baseUrl': 'assets/js', 
    'paths': { 
     'handlebars' : 'plugins/handlebars', 
     'controller' : 'controller', 
     'initialize' : 'initialize' 
    }, 
    'shim' : { 
     'handlebars': { 
      exports: 'handlebars' 
     }, 
     'controller' : { 
      deps: [ 
       'handlebars' 
      ] 
     } 
    } 
}); 

requirejs([ 
    'handlebars', 
    'initialize', 
    'controller' 
]); 

在controller.js文件我有这样的:

var source = $("#entry-template").html(); 
var template = Handlebars.compile(source); 

var context = {title: "My New Post", body: "This is my first post!"}; 
var ihtml = template(context); 

$('.testad').html(ihtml); 

但是,当我裹着这上面的代码,它似乎工作:

define(['handlebars'], function(Handlebars) { 
    // place above code here 
}); 

但问题是,我有define()之外的方法,它可以在其中不叫。

define(['handlebars'], function(Handlebars) { 
    // place above code here 
    function handleMe() { 
     // some codes here 
    } 
}); 

function callMe() { 
    handleMe(); 
} 

的另一个问题是,我有一个initialize.js,以查找属性my-controller并调用分配给它的功能。有点“模块化”。

define(['jquery'], function($) { 
$(function() { 
    $('[my-controller]').each(function(e, t) { 
     var a = $(t).attr('my-controller'); 
     'undefined' != typeof window[a] && $.isFunction(window[a]) ? window[a]($) : ''; 
    }); 
}); 

所以在我的HTML,如果我有<div my-controller="callMe"></div>,它会自动调用callMe()方法,其中,它是我的controller.js文件。但是将callMe()定义在里面,因为它不再是全局的,所以不能调用它。

回答

0

您遇到的所有问题都与范围有关。

在你的第一个问题中,handleMe只作为包装它的工厂函数中的一个变量存在。封闭之外没有任何东西可以看到它。它类似于此:

var fn = function() { 
    var a = 1; 
}; 
console.log(a); // undefined 
fn(); // a is set, but falls out of scope when the function returns 
console.log(a); // still undefined 

,当你在一个共享的范围内声明变量(或在全球范围内),这种“问题”是固定的这样的:

var a; 
var fn = function() { 
    a = 1; 
} 

console.log(a); // undefined 
fn(); // a is set in the parent scope 
console.log(a) // 1 

在第二个问题,在您尝试直接从DOM事件调用控制器方法的地方,除了尝试直接从全局范围(window)访问方法外,您正在做同样的事情。

我怀疑最好的解决方案是重新思考如何定义和组织模块。在一个典型的Requirejs项目中,通常你会定义你的模块,像这样:

// Controller.js 
define(['handlebars'], function (handlebars) { 
    var Controller = function() { 
     // Create your controller here. 
     // Create any DOM elements you need here 
    }; 
    Controller.prototype.initialize = function() { 
     // Bind the DOM events to controller methods 
    }; 
    Controller.prototype.method1 = function() {}; 
    Controller.prototype.method2 = function() {}; 
    Controller.prototype.method3 = function() {}; 

    return Controller 
}); 

// main.js 
require(['Controller'], function (Controller) { 
    var myController = new Controller(); 

    myController.initialize(); 
}); 
+0

谢谢安德鲁。我必须为每个define()创建一个新文件吗?就像上面给出的带有句柄的示例一样,我应该为handlebar逻辑创建controller-handlebar.js文件吗?并创建另一个文件,如say,controller-whateverplugin.js?我知道你可以做'define(['handlebars','whateverplugin'],函数(handlebars,whateverplugin){})',但是如果依赖太多,就很难阅读。有什么建议么? – basagabi

+0

这是使用require的最大优点之一,实际上它的主要目的(如CommonJS,它是一个模块/加载器/)。每个'define()'都有它自己的文件。你也不需要在'require.config()'的'paths:[]'部分放置'controller.js'。只要名称匹配('Controller' ==='assets/js/Controller.js'),Require就会知道在何处使用它并加载它。只要让它为你做的工作。声明可以变得很长,是的,但它只影响'define()'的第一行,并且作为回报,你可以拥有一个庞大的代码库,不存在依赖性头痛问题。 – Andrew