了解道场 AMD 加载功能未定义
Posted
技术标签:
【中文标题】了解道场 AMD 加载功能未定义【英文标题】:understanding dojo AMD loading- functions are undefined 【发布时间】: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 来调用它。我不知道该怎么做。
【问题讨论】:
【参考方案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"
。道场文件
存储在谷歌服务器上,由
<script src='http://ajax.googleapis.com/ajax/libs/dojo/1.9.1/dojo/dojo.js'>< /script>
在 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中使用,必须先加载到< 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 文件,您可以像下面这样引用它们。假设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。正确的?很抱歉在这里过分,但我很难阅读文档。 你太棒了。太感谢了。这会让我继续前进。 不客气。我很欣赏这些客气话。如果您对示例有任何疑问,请提出建议。我的解释可能会很啰嗦,会失去重点。以上是关于了解道场 AMD 加载功能未定义的主要内容,如果未能解决你的问题,请参考以下文章
5.10.0-kali7-amd64 中的 kallsyms_lookup_name 未定义错误