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

标签 javascript jquery requirejs mustache

我正在尝试将 Mustache 与 requireJS 和 jQuery 一起使用,由于 Chrome 的控制台输出正确,它似乎正在加载到浏览器中:

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

但是当我尝试使用 mustache 函数时,它给出错误 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);
});

最佳答案

问题

Mustache 是 AMD 感知的,因此当您加载 mustache.js 文件时,它会检测到它正在使用 AMD 加载程序 (RequireJS) 运行,调用 define并且不会将任何东西泄漏到全局空间中。耶!这是 AMD 感知模块的完美行为。如果没有 AMD 加载器,它会执行典型的操作:将单个符号导出到全局空间 (Mustache)。

但是,当您使用 Mustache 代码库提供的 jQuery 插件时,您会得到一个 eldritch abomination,这是一种既能识别 AMD 又能忽略 AMD 的生物,它不会泄漏任何东西给全局空间,但依赖于将事物泄漏到全局空间。基本上,发生的事情是 Mustache 的核心,它是 AMD 感知的,被包装在添加 jQuery 支持的代码中,但这段代码不是 AMD 感知的。总而言之,只有在存在 AMD 加载程序的环境中加载此代码时,它才能正常工作。

您得到的错误是因为虽然 Mustache 不会向全局空间泄漏任何内容,但 jQuery 插件希望在全局空间中找到 Mustache

选项

您有多种选择:

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

  2. 使用丑陋的 RequireJS hacks 让它工作。这包括故意将 Mustache 泄漏到全局空间中。 (讨厌!)为 mustache 模块声明一个 shim,即使它调用 define。 (当我尝试它时,它起作用了,但我不会打赌它是稳定的,因为 shim 用于调用define.)

  3. 将包装器(哈哈!)包装到样板中以使其正常运行。

让包装器正常运行

我更喜欢选项 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 包装器之后的代码:

    }));
    

一旦这 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 中运行它没有任何问题。

关于javascript - $.mustache() 已定义,但在调用 mustache() 时未定义 Mustache(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25419991/

相关文章:

javascript - 从剪贴板粘贴所有浏览器的按钮

javascript - Safari 6 调试控制台慢

javascript - RequireJS - 从页面内部看不到变量

twitter-bootstrap - 使用 RequireJS 在 Ladda 中未定义 Spinner

javascript - 使用模块模式和实例化新对象之间的区别

javascript - Jquery 对话框不提交表单

jquery - 动态向表添加行数

javascript - jQuery 如何让 $(this) 选择器触发多个类

jquery - 在 HTML5 进度条中使用 jQuery

javascript - 关闭 requirejs promise