【问题标题】:understanding dojo AMD loading- functions are undefined了解道场 AMD 加载功能未定义
【发布时间】:2013-12-03 21:48:39
【问题描述】:

我一直在试图让某人向我解释 dojo AMD 加载的工作原理,并让一段简单的代码工作。我知道如果使用例如 CDN,则必须调用 dojo 库并加载您希望使用的所有模块。我尝试根据主页上的活动来实现其他 javascript 函数,但我总是会得到未定义的函数或与未定义的 dojo 控件相关的错误。似乎最初加载的所有模块都不适用于其余代码。任何有用的解释将不胜感激。

          <link rel="stylesheet" type=
        "text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.4/dojo/resources
                           /dojo.css" />
          <link rel="stylesheet" type=
        "text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.4/dijit/themes/
                           tundra/tundra.css" />
          <link rel="stylesheet" type=
        "text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.4/dojox/mobile/themes/
                           iphone/iphone.css" />
         <title> DOJO </title>
         <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.8.4/
                   dojo/dojo.js" 
              data-dojo-config="async:true"></script> 

      <script type="text/javascript" src="Scripts/login.js"></script>
     <script type="text/javascript">
      require(["dojox/mobile/parser",
                "dojo/parser",
                "dojo/on",
                "dojo/request/xhr",
                "dijit/form/Form",
                "dojo/store/Observable",
                "dojo/store/Memory",
                "dijit/Toolbar",
                "dijit/Dialog",
                "dojo/io/script",
                "dojo/query",
                "dojo/_base/lang",
                "dijit/layout/ContentPane",
                "dojox/mobile/Button",
                "dojox/mobile/deviceTheme",
                "dojox/mobile/compat",
                "dojox/mobile/Heading",
                "dojox/mobile/TextBox",
                "dojox/mobile/Opener",
                "dijit/form/TextBox",
                "dijit/form/HorizontalSlider",
                "dijit/form/ValidationTextBox",
                "dijit/Calendar",
                "dojox/mobile/ScrollableView",
                "dojo/dom",
                "dojo/domReady!",
                "dojox/mobile"],

        function (dom, domReady ,mobile, ScrollableView, 
               parser, query, domClass, domStyle, on, event, xhr,Form,
             lang, Button, deviceTheme, compat, Heading) {
            dojox.mobile.parser.parse();
        });

</script> 

据我了解,我拥有上面代码的方式是我的界面将正确加载,并且 html 正文中的所有小部件都将显示并且工作正常。问题是我有一个从用户那里获取输入的表单,并且在按钮单击事件上调用一个处理 webrequests 的函数。我无法让它工作,这只是我放置此功能的位置的问题。我添加了一个简化版本:

我所做的是将该函数添加到脚本文件中,以将其与其余代码分开:

var dojoXhr;

function correctInput(div, td, msg) {
dojo.domStyle.set(div, 'display', '');
td.innerHTML = msg;
}

require(["dojo/_base/declare", "dojo/parser", "dojo/query", "dojo/dom-class", 
     "dojo/dom-style",   "dojo/on", 
     "dojo/_base/event",
     "dojo/request/xhr", "dijit/form/ValidationTextBox", "dojo/domReady!"], 
  function chklogin(declare, parser, query, dom-class, dom-style, 
      on, event, xhr,ValidationTextBox, domReady) {

   var lname = dijit.byId('login').get('value');
   var psswd = dijit.byId('password').get('value');
   var feedback = document.getElementById('feedback');
   var feedbackTD = dojo.query('td.feedback')[0];
   if (lname == '' || psswd == '') {
       correctInput(feedback, feedbackTD, 'Please enter a valid login!');
       dojo.domStyle.set(feedback, 'display', '');
       dojo.domStyle.set(document.getElementById('msgBodyOutter'), 'display', 'none');
       feedbackTD.innerHTML = "Please enter a valid login!";
       return;
   }
   if (!(lname == 'login') || !(psswd == 'password')) {
       correctInput(feedback, feedbackTD, 'Please enter a valid login!');
       return;
   }
   else {
       dojo.domStyle.set(feedback, 'display', '');
       dojo.domStyle.set(document.getElementById('msgBodyOutter'), 'display', 'none');
       feedbackTD.innerHTML = "THATS IT BRO!";
       return;
   }


});

我在 dojo 论坛上得到了建议,将我的函数放在定义函数中,然后使用 require 来调用它。我不知道该怎么做。

【问题讨论】:

    标签: dojo dojox.mobile


    【解决方案1】:

    似乎所有最初加载的模块都不可用 剩下的代码。

    您正在使用CDN 加载dojo 工具包。当您使用 CDN 时,您需要定义模块包的位置。您需要编辑 dojoConfig 才能使代码正常工作。

    请参阅这篇关于Using Custom Modules with a CDN 的文章。重要的部分是包对象。

    <script data-dojo-config="async: 1, dojoBlankHtmlUrl: '/blank.html',
            packages: [ {
                name: 'custom',
                location: location.pathname.replace(/\/[^/]+$/, '') + '/js/custom'
            } ]"
        src="//ajax.googleapis.com/ajax/libs/dojo/1.9.1/dojo/dojo.js">
    </script>
    

    编辑: 下面是一个简单的 dojo 应用程序。

    所以在我的例子中,创建一个名为 chklogin 的模块,然后 require 它,然后 当用户单击按钮时,它将调用该模块 chklogin 在主 require[] 函数中。对吗?

    我会说是的。你是对的。我认为你的概念是一个可行的选择。我希望这个例子有助于实现 define() 来创建你自己的模块。当你发展你的想法时,我会尽我所能提供帮助。如果有空,您可以在此处download the project

    目录结构:

    /index.html
    /js/config.js
    /js/controller/Controller.js
    /js/modules/MyFirstModule.js
    

    /index.html

    <!doctype html>
    <html>
        <head>
        <meta charset="UTF-8">
         <title>Demo</title>
        <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.9.1/dijit/themes/claro/claro.css">
        <script src="js/config.js"></script>
        <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.9.1/dojo/dojo.js"></script>
        <script>
            require(["app/Controller", "dojo/domReady!"], function(Controller) {
    
                //Initiate the entire application by calling main method of our Controller class. 
                Controller.main();
    
                //Call our getter method of the Controller class to show how to access a private variable.
                console.log(Controller.getWelcomeMessage());
            });
        </script>
        </head>
    
        <body class="claro" id="appBody"></body>
    </html>
    

    /js/config.js

    我们使用 packages 来引用 CDN dojo 文件。现在我们可以通过我们的包名来调用 dojo 类 例如,"dojo/domReady!""dijit/form/Button""dojox/app/main"。道场文件 存储在谷歌服务器上,由 &lt;script src='http://ajax.googleapis.com/ajax/libs/dojo/1.9.1/dojo/dojo.js'&gt;&lt; /script&gt; 在 index.html 文件中。

    我们在这里创建自己的自定义包。这可能适用于您的模块、小部件等。包 位置将映射到您存储自定义 dojo 文件的 javascript 目录。 例如,myModules 可以在 /js/modules 目录中找到。您将参考任何自定义 dojo 文件通过"myModules/MyModule" 定位并加载"/myModules/MyModule.js" 文件。

    有关baseURL 的解释,请参阅:http://dojotoolkit.org/documentation/tutorials/1.9/hello_dojo/ “定义和要求模块”。这段代码注册了我们自己的包的正确位置,所以 我们可以从 CDN 加载 Dojo,同时仍然能够加载本地模块。

    我创建了一个名为"app" 的包,如下所示。这就是我在项目中初始化应用程序的方式。 这是为了让我能够尽我所知地保持代码分离。它已加载并 在 index.html 页面中调用。所以我给它一个app的包名。它物理上位于 js/controller/Controller.js 文件。

    这个dojoConfig对象在index.html中使用,必须先加载&lt; script src='...dojo.js' &gt;标签。

    var dojoConfig = {
        async: true,
        tlmSiblingOfDojo: false,
        baseUrl: location.pathname.replace(/\/[^/]*$/, ''),
        packages: [
            { name: "myModules", location: "js/modules" },
            { name: "app", location: "js/controller", main: "Controller" }
        ]
    };
    

    如果您选择在您自己的服务器上托管 dojo 文件,您可以像下面这样引用它们。假设dojo js文件位于"/js/dojo/*"目录下。

    packages: [
            { name: "dojo", location: "dojo/dojo" }, 
            { name: "dijit", location: "dojo/dijit" },
            { name: "dojox", location: "dojo/dojox" },
            { name: "myModules", location: "js/modules" },
            { name: "app", location: "js/controller", main: "Controller" }
        ]
    

    /js/controller/Controller.js

    这是我用来初始化网络应用程序的控制器。

    define(["myModules/MyFirstModule"], function(MyFirstModule) {
    
        //Private Variables...
        var privateVariable1 = "Welcome to my Dojo Application!";
        var privateVariable2;
    
        /**
         * init. This is a private function that is only available within this object.
         */
        init = function() {
            // proceed directly with startup
            console.log("Startup functions are firing...");
    
            //Render our "form" which only contains a single text box.
            renderForm();
        },
    
        renderForm = function() {
            MyFirstModule.createForm("appBody");
        }
    
        /**
         * Enclose all public methods in the return object
         */
        return {
    
            /**
             * main. This is a public function that can be called from other code.
             */
            main: function() {
    
                //Run init() method.
                init();
            },
    
            /**
             * getWelcomeMessage. This public function returns the value of the privateVariable1.
             * This mimics a getter method.
             */
            getWelcomeMessage: function() {
                return privateVariable1;
            }
        };
    
    }); //end define
    

    /js/modules/MyFirstModule.js

    这是一个自定义模块的示例。 Controller 类需要它作为依赖项。

    define([
        //The required dependencies for this module.
        "dojo/dom", "dojo/on", "dijit/form/TextBox", "dijit/form/Button"
    ], function(dom, on, TextBox, Button){
        // Once all modules in the dependency list have loaded, this
        // function is called to define the myModules/myFirstModule module.
        //
        // The dojo/dom module is passed as the first argument to this
        // function; additional modules in the dependency list would be
        // passed in as subsequent arguments (on, TextBox, and Button).
    
        // Private variables
        var firstNameTextBox;
        var submitButton;
    
        privateFunction = function() {
            console.log("I am a private function. I can only be called from this class.");
        };
    
        // This returned object becomes the defined value of this module when called elsewhere.
        return {
            /**
             * createForm. This method creates a simple form. Textbox and button.
             * @param placeMeHere This is where to place the form elements. In this demo, the are placed in the 
             * body of the html document. This is executed in the Controller class.
             */
            createForm: function(placeMeHere) {
    
                //Create new TextBox.
                firstNameTextBox = new TextBox({
                    name: "firstname",
                    value: "" /* no or empty value! */,
                    placeHolder: "type in your name"
                }, "firstname");
    
                //Place me in the DOM.
                firstNameTextBox.placeAt(placeMeHere);
    
                //Render 
                firstNameTextBox.startup();
    
                //Create Button
                submitButton = new Button({
                    label: "Say Hi"
                }, "submitButton");
                submitButton.placeAt(placeMeHere);
                submitButton.startup();
    
                //Greet the user.
                on(submitButton, "click", function(evt){
                    console.log("Hi there, " + firstNameTextBox.get("value"));
                });
    
            }
        };
    });
    

    【讨论】:

    • 感谢您的回复。不确定我是否理解...我实际上是在尝试调用 chklogin 函数,因为它被错误检查为未定义。我得到了 dojo 库的其余部分来加载,我只是不确定在哪里放置 chklogin 函数以便它工作。
    • 好的,抱歉。我还建议使用 define() 将该代码移动到模块中。你试过Hello Dojo 教程了吗?它展示了如何使用 define 实现您的目标。
    • 不,感谢您的帮助。我看了看,不是一个很好的读者。当有人告诉我时,我理解。我的理解是他们在 .js 文件中创建了一个名为 mymodule 的模块;然后在主程序中需要该模块(mymodule)并将其用作函数。因此,在我的例子中,创建一个名为 chklogin 的模块,然后 require 它,当用户单击按钮时,它将从主 require[] 函数中调用该模块 chklogin。正确的?很抱歉在这里过分,但我很难阅读文档。
    • 你太棒了。太感谢了。这会让我继续前进。
    • 不客气。我很欣赏这些客气话。如果您对示例有任何疑问,请提出建议。我的解释可能会很啰嗦,会失去重点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-19
    • 2020-11-27
    • 2015-12-01
    相关资源
    最近更新 更多