Dojo AMD:无法在要求中调用函数

Posted

技术标签:

【中文标题】Dojo AMD:无法在要求中调用函数【英文标题】:Dojo AMD: Can't call a function inside a require 【发布时间】:2012-03-26 11:26:35 【问题描述】:

我确实是 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,如果您将代码分成许多小函数,您是否会重新执行每个函数中的“要求”?或者您是否将所有功能与完整列表放在一个“要求”中? 如果你用第二种方法,你怎么能从小部件事件中调用这些函数呢?

【问题讨论】:

【参考方案1】:

最简单的方法是定义您自己的模块。先看看这个教程:

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>

【讨论】:

那么,返回对象中的fillReportTable: fillReportTable会暴露fillReportTable()函数吗? 是的,没错。当 mymodule 模块为required 时,AMD 加载程序将为该模块加载一个特定的 JS 文件(在我们的例子中为“mymodules/mymodule.js”。在该 JS 文件中,您将一个函数传递给define,此函数用于“导出”模块的功能。在您的情况下,模块表示一个具有两个辅助函数的对象。 那么现在我可以从 require 之外的任何地方调用 mymodule.fillReportTable() 了吗? 在上面需要设置对象dojo.setObject('fillReportTable', mymodule.fillReportTable)。然后在require之外做一个getObject。 var fillReportTable = dojo.getObject('fillReportTable');现在 fillReportTable() 在全局空间中。【参考方案2】:

试试这个:

require([...], function() 
    var myFunctions = dojo.getObject('myFunctions', true);
    myFunctions.createNewRow = function(...) 
        ...
    ;
);

您现在可以使用

从任何地方调用您的函数
myFunctions.createNewRow();

如果你不想要“myFunctions”,你可以这样做

require([...], function() 
    var createNewRow = function(...) ;

    dojo.setObject('createNewRow', createNewRow);
);

【讨论】:

【参考方案3】:

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();

【讨论】:

以上是关于Dojo AMD:无法在要求中调用函数的主要内容,如果未能解决你的问题,请参考以下文章

使用Dojo lang.hitch将参数传递到调用的函数中

在重新加载/刷新页面时,未调用dojo / ready函数

了解道场 AMD 加载功能未定义

以编程方式更改值时触发Dojo Select onChange事件触发

Dojo 1.7 Ajax 内容和 AMD 要求

当 Dojo 自动完成器的值改变时调用 java-script 函数