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
希望这对您有所帮助。
我正在尝试使用 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
希望这对您有所帮助。