2015-10-01 49 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