道场 AMD:无法在 require 中调用函数
-
09-12-2019 - |
题
我确实是 dojo 的新手,但当我开始使用 dojo 版本 1.7.2 开发新应用程序时,我也想使用新的 AMD 函数语法。不幸的是我似乎不明白。:-(
最让我烦恼的是我不能简单地调用“require”块内的任何函数。例如,我有一个页面,打开时会创建一个动态表,每行中有几个小部件。然后我有一个按钮,每次按下都会添加一个空行。
如果没有 AMD 语法,这将很容易:
- 将我所有的“dojo.require()”放在 HEAD 中
- 然后创建一堆我自己的函数来创建表格和小部件
- 添加行函数可以轻松访问我之前的函数填充的任何全局变量
但AMD的情况是这样的:
初始函数创建表和小部件:
function fillReportTable(repId) {
require(["dojo/dom-construct", "dojo/dom-attr", "dijit/form/FilteringSelect",
"dojo/data/ItemFileReadStore", "dijit/form/ComboBox", "dijit/form/DateTextBox", "dijit/form/Select", "dojo/store/Memory"],
function (domConstruct, domAttr, FilteringSelect, ItemFileReadStore, ComboBox, DateTextBox, Select, Memory) {
// a lot of code to create the table, consisting of SEVERAL functions
function createNewRow(tbl) { ...}
function function1 () {... }
function function2 () {... }
function function3 () {... }
}
现在,“添加空行”按钮调用其自己的函数“addEmptyRow”。
但在这个函数中我必须:
- 再次对每个 dojo 模块执行其他要求
- 我无法使用“fillReportTable”函数“内部”的任何函数。例如“createNewRow”函数
function addEmptyRow() {
require(["dojo/dom-construct", "dojo/dom-attr", "dijit/form/FilteringSelect",
"dojo/data/ItemFileReadStore", "dijit/form/ComboBox", "dijit/form/DateTextBox", "dijit/form/Select", "dojo/store/Memory"],
function (domConstruct, domAttr, FilteringSelect, ItemFileReadStore, ComboBox, DateTextBox, Select, Memory) {
// a lot of code to create the table, consisting of SEVERAL functions
}
对于 AMD 来说,这一切似乎都非常复杂。
或者我在这里遗漏了一些明显的东西?
使用AMD,如果您将代码分成许多小函数,您是否会在每个函数中重新执行“require”?或者您是否将所有功能与完整列表一起放入一个“require”中?
如果您采用第二种方式,如何从小部件事件中调用这些函数?
解决方案
最简单的方法是定义您自己的模块。首先看一下这个教程:
http://dojotoolkit.org/documentation/tutorials/1.7/modules/
现在定义您自己的模块,例如“./js/mymodules/mymodule.js”(相对于 HTML 页面):
define([
"dojo/dom-construct",
"dojo/dom-attr",
"dijit/form/FilteringSelect",
"dojo/data/ItemFileReadStore",
"dijit/form/ComboBox",
"dijit/form/DateTextBox",
"dijit/form/Select",
"dojo/store/Memory"
], function (domConstruct, domAttr, FilteringSelect, ItemFileReadStore, ComboBox, DateTextBox, Select, Memory) {
function fillReportTable(repId) {
// a lot of code to create the table, consisting of SEVERAL functions
function createNewRow(tbl) { ...}
function function1 () {... }
function function2 () {... }
function function3 () {... }
}
function addEmptyRow() {
// a lot of code to create the table, consisting of SEVERAL functions
}
// Return an object that exposes two functions
return {
fillReportTable: fillReportTable,
addEmptyRow: addEmptyRow
}
});
并像这样使用你的模块:
<html>
<head>
<script>
var dojoConfig = {
baseUrl: "./js/",
packages: [
{ name: "dojo", location: "lib/dojo" },
{ name: "dijit", location: "lib/dijit" },
{ name: "dojox", location: "lib/dojox" }
]
};
</script>
<script data-dojo-config="async: true" src="js/lib/dojo/dojo.js"></script>
</head>
...
<script>
require([
"mymodules/mymodule"
], function (mymodule) {
mymodule.fillReportTable(...);
mymodule.addEmptyRow(...);
});
</script>
其他提示
尝试这个:
require([...], function() {
var myFunctions = dojo.getObject('myFunctions', true);
myFunctions.createNewRow = function(...) {
...
};
});
您现在可以使用以下方式从任何地方调用您的函数
myFunctions.createNewRow();
如果你不想要“myFunctions”,你可以这样做
require([...], function() {
var createNewRow = function(...) {};
dojo.setObject('createNewRow', createNewRow);
});
Paul Grime 给了你一个很好的例子,所以我只是分享一些想法。
您不必在每个函数中定义所有模块,这会浪费大量空间。尽管如此,即使您尝试多次加载一个模块,Dojo 也只会加载一次。
这是我最新项目的简化模块,具有相当无意义的功能:
//app module in 'my' folder
define(
[
'app/elements',
'dojo/query',
'dojo/on',
'dojo/fx',
'dojo/_base/fx',
'dojo/dom-construct',
'dojo/_base/event'
//and so on.....
],
function(elements, q, on, fx, baseFx, constr, event)
{
return {
init : function()
{
var node = q(elements.loading);
this.removeNode(node);
this.addEvents();
},
removeNode : function(node)
{
node.remove();
},
addEvents : function()
{
$(elements.buttons).on('click', function(e)
{
alert(q(e).attr('id') + ' was clicked!');
});
}
}
}
然后我通过使用获取模块
define(
[
'my/app',
],
function (app)
{
app.init();
}