Dojo AMD 不加载自定义模块

Dojo AMD not loading custom module

我正在尝试使用 ArcGIS API、Dojo 和 Flask 制作 Web 应用程序。我想首先制作一个 "file uploads" 对话框,我试图使用 Dojo 1.7 AMD 约定(即 "define")将其定义为自己的模块。

这是我的文件结构:

\static
     home.js
     fileUpload.js
\templates
     home.html
main.py

这是对话框的代码(从 Dojo 教程之一复制而来)。我基本上是在尝试将所有与对话框相关的功能(即显示和隐藏)放在一个模块中:

define([
    "dijit/registry",
    "dijit/Dialog",
    "dijit/form/Button",
    "dojo/ready",
    "dojo/domReady!"
], function (registry) {


    console.log("HELLO WORLD");


    return {
        // Show the dialog
        showDialog: function() {
            registry.byId("uploads").show();
        },

        // Hide the dialog
        hideDialog: function() {
            registry.byId("uploads").hide();
        }
    }

});

在 "home.js" 结束时,我尝试创建对话框模块的实例:

var fu = new fileUpload();

然后在我的 "home.html" 文件中,我定义了实际的对话框并尝试使用 "fu" 对象的变量作为关闭和打开对话框的事件处理程序:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">

    <title>morPOP</title>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
    <link rel="stylesheet" href="https://js.arcgis.com/4.5/esri/css/main.css">
    <link rel="stylesheet" href="../static/css/home.css">

    <script src="https://js.arcgis.com/4.5/"></script>

    <script src="../static/js/home.js"></script>
</head>

<body>
    <!-- Map -->
    <div id="viewDiv"></div>

    <!-- Upload Button -->
    <div class="btn-toolbar" role="toolbar" aria-label="Toolbar with button groups">
        <button type="button" id="uploadbtn" class="btn btn-primary" onclick="fu.showDialog()">Upload</button>
    </div>

    <!-- Upload Dialog -->
    <div class ="dijitHidden">
        <div id="uploads" data-dojo-type="dijit/Dialog" data-dojo-props="title:'Upload Files'">
            <p>The following files must be uploaded to run a simulation. File names must match those listed below.</p>
            <p>Acceptable file extensions: .txt or .csv</p>
            <ul>
                <li>Geographic data</li>
                <ul>
                    <li>Age_Dissemination</li>
                </ul>
                <li> Probability Data </li>
                <ul>
                    <li>ageContactDuration_hospital_nurse</li>
                    <li>ageContactDuration_hospitalPatient</li>
                    <li>ageContactNumber_hospital</li>
                </ul>
                <li> ??? </li>
                <ul>
                    <li>Census_Division_Mapping</li>
                </ul>
            </ul>

            <button onclick="fu.hideDialog();">Finish</button>
        </div>
    </div>

</body>

</html>

我在 google Chrome 开发人员控制台中得到的错误如下:

Uncaught TypeError: Cannot read property 'on' of undefined
    at new g (init.js:56)
    at home.js:51
    at Q (init.js:18)
    at init.js:18
    at A (init.js:18)
    at ea (init.js:18)
    at d (init.js:20)
    at HTMLScriptElement.<anonymous> (init.js:23)

我不确定 "on" 属性 错误指的是什么。有人有什么想法吗?为什么我不能声明我的模块的一个实例?

** 编辑 ***

我已将 home.js 文件更改为 "require" fileUpload.js,但当我尝试单击 "submit" 按钮时,我现在收到以下错误:

(index):24 Uncaught ReferenceError: fu is not defined
  at HTMLButtonElement.onclick ((index):24)

请查看我更新后的 home.js 文件的以下插件:https://plnkr.co/edit/9dFVHsFOCji1aE0ZeLRQ?p=preview

当使用 AMD 时,您可以像使用 define() 那样定义事物来管理您的依赖关系,但是模块的客户端必须使用 require() 函数导入它,see docs,同时您尝试通过 new 实例化所需的模块是不正确的。

要在 DOM 处理程序中使用某些模块,您需要额外的包装器,例如如果您在范围内有此功能,您的 HTML 将成为 onclick="whenClicked()"

function whenClicked() {
  require(['fileUpload'], function(fu) {
    fu.showDialog();
  });
}

当然假设 'fileUpload' 是正确指定的 AMD 模块。

编辑: Plunker 上 OP 示例的修改版本: https://plnkr.co/edit/QFckwndDicGpTfzhGwFC?p=preview

注意 fileUpload.js 模块定义已更改,以便显示基本警报:

define([
"dijit/registry",
"dijit/Dialog",
"dijit/form/Button",
"dojo/domReady!"
], function (registry) {
  return {
    // Show the dialog
    showDialog: function() {
        //registry.byId("uploads").show();
        alert("this is file upload mock");
    }
  }
});

以及 home.js whenClicked 的托管定义:

function whenClicked() {
  require({
    packages: [
      {name: "fileUpload", 
      // location should point to fileUpload.js on your target server
      location: "https://run.plnkr.co/uv2ILkhQpQC2wqRV",
      main: "fileUpload"}
    ]},
    ['fileUpload'], function(fu) {
      console.log("fileupload");
      fu.showDialog();
  });
}

请注意,显示模块的 location 与 bRIMOs 在其他答案中所说的类似。然而,我的方法只为这个由 require 包装的特定代码配置位置; bRIMO 的方法是全球性的。

但是请注意,每次重新加载编辑器时,Plunker 都在重建 location URL:/ 这实际上意味着您修复了位置前缀,运行 没问题,重新加载 Plunker 页面,又坏了。

我认为您错过了在 dojo 配置中配置路径以便 AMD 加载程序访问 fileupload.js 文件,在 dojoConfig doc 中有许多类型的配置(basURl,包, paths ...) ,下面你可以看到如何使用 packges 进行配置,dojo 将毫无问题地使用 require 加载你的文件

因此,在加载您的 arcgis js 之前 api <script src="url_api_js"></script> 请务必执行以下操作(使用 dojoConfig 变量配置 dojo)

<script type="text/javascript">
   var dojoConfig = {
       packages: [
           { 
                name: "mypackage", 
                location: location.pathname.replace(/[^\/]+$/, '') +"/static"
           }
       ]
   };
<script>
<script src="url_api_js"></script>

并且您的代码内部使用 package/name 文件的名称,如下所示

require(['mypackage/fileUpload'], function(upload) {
    upload.showDialog();
});

注意:根据服务器类型,位置可能会发生变化,在此示例中,位置如下:{location_name}/static/fileupload.js

希望这对您有所帮助。