$ .mustache()已定义,但在调用mustache()时未定义Mustache

时间:2014-08-21 06:54:03

标签: javascript jquery requirejs mustache

我正在尝试使用Mustache以及requireJS和jQuery,并且它似乎被加载到浏览器中,因为Chrome的控制台输出正确:

>$.mustache
<function (template, view, partials) {
    return Mustache.render(template, view, partials);
} 

但是当我尝试使用胡子函数时,它会给出错误ReferenceError: Mustache is not defined并指向mustache.js文件本身的第588行:

$.mustache = function (template, view, partials) {
    return Mustache.render(template, view, partials);
};

以下是我在main.js文件中调用它的方法:

require(['mustache'], function(Mustache){
    var view = {test:'TEST'};
    var temp = '{{test}}!!!';
    $.mustache(temp,view);
});

2 个答案:

答案 0 :(得分:3)

问题

Mustache具有AMD感知能力,因此当您只加载mustache.js文件时,它会检测到它正在运行AMD-loader(RequireJS),调用define并且不会泄漏任何内容到全局空间。好极了!对于支持AMD的模块,这是完美的行为。如果没有AMD-loader,它就是典型的事情:将单个符号导出到全局空间(Mustache)。

然而,当你使用Mustache代码库提供的jQuery插件时,你会得到一个 eldritch憎恶,一个既有AMD感知却又忽略了AMD的生物,它不泄漏任何东西全球空间,但依赖于泄漏到全球空间。基本上,发生的事情是Mustache的核心,它是AMD感知的,包含在添加jQuery支持的代码中,但是这些代码 AMD-aware。总而言之,只有在存在AMD加载程序的环境中加载时,此代码才能正常运行。

你得到的错误是因为虽然Mustache没有泄漏到全局空间,但jQuery插件希望在全局空间中找到Mustache

选项

您可以选择多种方式:

  1. 请勿使用与Mustache捆绑在一起的jQuery插件。

  2. 使用丑陋的RequireJS黑客来使其工作。这包括故意将Mustache泄漏到全球空间。 (哎呀!)为shim模块声明mustache,即使它调用define。 (当我尝试它时,它可以工作,但我不会打赌它完全稳定,因为shim用于调用define的代码。)

  3. 将包装纸(ha!)包装到样板中的样板中。

  4. 让包装器行为

    我更喜欢选项3.这可以使用Grunt或makerake自动完成。配方是按顺序连接4个文件:

    1. 在Mustache的jQuery包装器之前放置的代码:

      (function (factory) {
          // If in an AMD environment, define() our module, else use the
          // jQuery global.
          'use strict';
          if (typeof define === 'function' && define.amd)
              define(['jquery', 'mustache'], factory);
          else
              factory(jQuery, Mustache);
      }(function (jQuery, Mustache) {
          'use strict';
      
    2. 文件mustache/wrappers/jquery/mustache.js.pre。这与Mustache捆绑在一起。

    3. 文件mustache/wrappers/jquery/mustache.js.post。这与Mustache捆绑在一起。

    4. 在Mustache的jQuery包装器之后放置的代码:

      }));
      
    5. 将这4个文件按此顺序组合在一起后,您将获得一个可以使用RequireJS加载的文件。

      这是一个例子。在以下示例中,所有第三方组件都随Bower一起安装。 js子目录包含如上所述连接四个文件的结果,此结果名为jquery.mustache.js

      <!DOCTYPE html>
      <html>
        <head>
          <meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8"/>
          <script type="text/javascript" src="bower_components/requirejs/require.js"></script>
          <script id="template" type="text/html">
            <p>Hi, {{name}}</p>
          </script>
        </head>
        <body>
          <script>
            require.config({
              baseUrl: ".",
              paths: {
                jquery: "bower_components/jquery/dist/jquery",
                mustache: "bower_components/mustache/mustache",
                "jquery.mustache": "js/jquery.mustache"
              }
            });
            require(["jquery", "jquery.mustache"], function ($) {
              console.log($.mustache);
              $(document.body).append($("#template").mustache({name: "blah"}));
            });
          </script>
        </body>
      </html>
      

      我在Chrome中运行它没有任何问题。

答案 1 :(得分:1)

当通过CommonJS接口调用时,胡须模块不会导出全局Mustache对象(如require.js那样) - 当通过标记包含模块时,它会导出此对象。

你可以在jquery.mustache.js源代码的第23行看到这个: jquery.mustache.js (gist)

jQuery插件引用此全局Mustache对象,当require.js导入jquery.mustache.js时,该对象不存在。

您需要告诉require.js导出Mustache对象 - 这是通过require.config设置完成的,使用 shim 属性:

require.config({
  shim: {
    'mustache': {
        exports: 'Mustache'
    }
  }
});

在调用 require()之前包含此代码,并且(全局)Mustache对象可用于 $ .hustache 函数(即它将起作用)