понимание загрузки dojo AMD - функции не определены

Я пытался заставить кого-нибудь объяснить мне, как работает загрузка dojo AMD, и заставить работать простой фрагмент кода. Я понимаю, что при использовании, например, CDN необходимо вызвать библиотеку dojo и загрузить все модули, которые вы хотите использовать. Я пытался реализовать другие функции javascript на основе активности на главной странице, и я всегда получаю либо неопределенную функцию, либо ошибку, связанную с неопределенным элементом управления додзё. Создается впечатление, что все модули, которые загружаются изначально, недоступны для остального кода. Любые полезные объяснения будут действительно оценены.

          <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 будут отображаться, и он отлично работает. Проблема в том, что у меня есть форма, которая получает ввод от пользователя, а событие нажатия кнопки вызывает функцию, которая обрабатывает веб-запросы. Я не мог заставить это работать, и это просто проблема с тем, где я размещаю эту функцию. Я добавил упрощенную версию:

Что я сделал, так это добавил эту функцию в файл сценария, чтобы отделить ее от остального кода:

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;
   }


});

Я получил совет на форуме додзё поместить мою функцию в функцию определения, а затем использовать требование для вызова всего этого. Я не мог понять, как это сделать.


person vbNewbie    schedule 03.12.2013    source источник


Ответы (1)


Создается впечатление, что все модули, которые загружаются изначально, недоступны для остального кода.

Вы используете CDN для загрузки додзе Инструментарий. Когда вы используете CDN, вам необходимо определить расположение пакетов модулей. Вам нужно отредактировать dojoConfig, чтобы код заработал.

См. эту статью об использовании пользовательских модулей с 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>

Редактировать: Ниже показано простое приложение для додзё.

Итак, в моем случае создайте модуль с именем chklogin, затем потребуйте его, и когда пользователь нажмет кнопку, он вызовет этот модуль chklogin из основной функции require[]. Правильный?

Я бы сказал да. Ты прав. Я думаю, что ваша концепция является жизнеспособным вариантом. Я надеюсь, что этот пример поможет вам реализовать функцию define() для создания ваших собственных модулей. Я постараюсь помочь, чем смогу, по мере развития вашей идеи. Вы можете загрузить проект здесь, пока он доступен.

Структура каталога:

/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

Мы используем пакеты для ссылки на файлы CDN dojo. Теперь мы можем вызывать классы додзё по имени нашего пакета. Например, "dojo/domReady!", "dijit/form/Button", "dojox/app/main". Файлы додзё хранятся на серверах Google, на которые ссылается <script src='http://ajax.googleapis.com/ajax/libs/dojo/1.9.1/dojo/dojo.js'>< /script> в файле index.html.

Здесь мы создаем наши собственные пользовательские пакеты. Это могут быть ваши модули, виджеты и т. д. Расположение пакетов будет отображаться в каталоге javascript, в котором вы храните свои пользовательские файлы dojo. Например, myModules можно найти в каталоге /js/modules. Вы будете ссылаться на любые пользовательские файлы додзё через "myModules/MyModule", который находит и загружает "/myModules/MyModule.js" файл.

Объяснение baseURL см. по адресу: http://dojotoolkit.org/documentation/tutorials/1.9/hello_dojo/ "Определение и требование модулей". Этот код регистрирует правильное расположение наших собственных пакетов, поэтому мы можем загружать Dojo из CDN, сохраняя при этом возможность загрузки локальных модулей.

Я создал пакет под названием "app", как вы можете видеть ниже. Вот как я инициализирую свое приложение в своем проекте. Это было разработано, чтобы позволить мне сохранить разделение кода настолько хорошо, насколько я знаю. Он загружается и вызывается на странице index.html. Поэтому я даю ему имя пакета приложения. Физически он находится в файле js/controller/Controller.js.

Этот объект dojoConfig используется в index.html и должен быть загружен до тега < script src='...dojo.js' >.

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

если вы решите разместить файлы додзё на собственном сервере, вы можете ссылаться на них, как показано ниже. Предположим, что файлы 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/контроллер/Контроллер.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

Это пример пользовательского модуля. Это требуется классу контроллера в качестве зависимости.

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"));
            });

        }
    };
});
person medokr    schedule 03.12.2013
comment
Спасибо за ответ. Не уверен, что понимаю... На самом деле я пытаюсь вызвать функцию chklogin, так как она проверяется на ошибку как неопределенная. Я загружаю остальную часть библиотеки dojo, я просто не уверен, где разместить функцию chklogin, чтобы она работала. - person vbNewbie; 04.12.2013
comment
Хорошо, извини. Я бы также рекомендовал переместить этот код в модуль, используя функцию define(). Вы уже пробовали руководство Hello Dojo? Он показывает, как достичь вашей цели с помощью define. - person medokr; 04.12.2013
comment
нет, спасибо за помощь. Я смотрел на это и не являюсь большим читателем. Я понимаю, когда кто-то говорит это мне. Насколько я понимаю, они создают модуль с именем mymodule в файле .js; затем в основной программе требуется этот модуль (mymodule) и используется как функция. Итак, в моем случае создайте модуль с именем chklogin, затем потребуйте его, и когда пользователь нажмет кнопку, он вызовет этот модуль chklogin из основной функции require[]. Правильный? извините за излишнее излишество, но мне трудно читать документацию. - person vbNewbie; 04.12.2013
comment
ты обалденный. Бесконечно благодарен. Это заставит меня двигаться. - person vbNewbie; 04.12.2013
comment
Пожалуйста. Я ценю добрые слова. Сообщите, если у вас есть какие-либо вопросы по примеру. Я могу быть многословным и терять фокус в своих объяснениях. - person medokr; 04.12.2013