Javascript 将HandlebarJS与RequireJS一起使用,ReferenceError:未定义HandleBar
当使用requirejs加载handlebarjs时,我得到一个ReferenceError:Handlebars未定义消息 这是我在app.js文件中的配置Javascript 将HandlebarJS与RequireJS一起使用,ReferenceError:未定义HandleBar,javascript,jquery,requirejs,handlebars.js,Javascript,Jquery,Requirejs,Handlebars.js,当使用requirejs加载handlebarjs时,我得到一个ReferenceError:Handlebars未定义消息 这是我在app.js文件中的配置 requirejs.config({ 'baseUrl': 'assets/js', 'paths': { 'handlebars' : 'plugins/handlebars', 'controller' : 'controller', 'initialize' : 'i
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,它查找我的控制器属性并调用分配给它的函数。有点模块化
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中,如果我有,它会自动调用callMe方法,它位于controller.js文件中。但是将callMe放在define中,无法调用它,因为它不再是全局的。您遇到的所有问题都与作用域有关 在第一个问题中,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
// 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();
});
在第二个问题中,当您试图直接从DOM事件调用控制器方法时,除了尝试直接从全局范围窗口访问这些方法之外,您正在做同样的事情
我认为最好的解决方案是重新思考如何定义和组织模块。在典型的Requirejs项目中,通常您会这样定义模块:
var a;
var fn = function () {
a = 1;
}
console.log(a); // undefined
fn(); // a is set in the parent scope
console.log(a) // 1
// 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();
});
谢谢安德鲁。我是否必须为每个定义创建一个新文件?就像上面给定的把手示例一样,我是否应该专门为把手逻辑创建controller-handlebar.js文件?创建另一个文件,比如controller-whateverplugin.js?我知道你可以让define['handlebar','whateverplugin'],function handlebar,whateverplugin{}但是如果依赖项太多,那就很难阅读了。有什么建议吗?这是使用require的最大优点之一,实际上它的主要用途和CommonJS一样,它是一个模块/加载程序/。每个define都有自己的文件。您也不需要将“controller.js”放在require.config的路径:[]部分。只要名称与Controller===assets/js/Controller.js匹配,Require就会知道在哪里找到它并在使用它之前加载它。就让它为你工作吧。声明可以很长,是的,但它只影响定义的第一行,作为回报,您可以拥有大量的代码库,而不必担心依赖性问题。