1. 确保DOM可以
一个是ready函数,可以将其包括在require()函数中,它会在HTML元素和任何模块加载之后才执行。另一个是可以在require()函数中使用dojo/domReady!(感叹号表示domReady是AMD加载器插件)插件。
esri/Map -加载特定于创建地图的代码
esri/views/MapView -加载允许以2D查看地图的代码
dojo/domReady! -确保在执行代码之前DOM可用。
2.dojo相关知识
①:在 HTML 5 中通常在 html 标签中加入 lang=en,但是在使用 Dojo 小部件时一定要去掉,否则会出现 “dojo/parse::parse() error” 错误,如图:
解决办法: 如果在 html 标签中添加了 lang=en,那么必须在 dojoConfig 中加入 locale:'en' ,要是 html 标签中不加,在 dojoConfig 中也不添加 locale:'en' 。
代码如下:
<script>
dojoConfig = {
isDebug: true,
async: true,
locale:'en'
};
②:dojo/parse 功能模块:我们在使用 dojo 中的面板组织页面内元素时,需要在 require 函数中引入小部件的标签属性,用于解析功能模块,在页面中通过 data-dojo-type 标签属性使用了 Dojo 小部件,例如,我们调用 dojo 的面板,代码如下:
<div data-dojo-type="dijit/layout/ContentPane" style="width:100px;height:200px;float:left">
</div>
例如我们使用 dojo 的按钮,代码如下:
<div data-dojo-type="dijit/form/Button">相关信息</div>
如果需要在按钮小部件中添加 onClick 事件,代码如下:
<div data-dojo-type="dijit/form/Button">
相关信息
<script type="dojo/on" data-dojo-event="click" data-dojo-args="evt">
makeAboutBox();
</script>
</div>
上面的代码就是,当点击按钮时,执行 makeAboutBox() 函数。
但是我们通过 data-dojo-type 指定的小部件,并不是标准的 HTML,浏览器不直接对他们进行解析,因此需要在页面加载完成后,对整个页面的所有标签进行解析,将它转换为浏览器可以识别的标记,解析小部件标签属性需要用到 dojo/parser 功能模块,需要我们在调用 require 函数时,将它包含进来。调用 dojo/parser 功能模块的 parse 函数,来解析小部件标签属性。
- 代码如下:
require(["dojo/parser", "dijit/layout/ContentPane", "dijit/form/Button", "dojo/domReady!"], function(parser){
parser.parse();
});
3. Dojo中的事件机制
① Dojo的事件 API:dojo/on 的调用方式为: on(元素,事件名称,处理函数)
例如我们要实现单击按钮时将 div 变为蓝色,当鼠标经过时变为红色。
代码如下:
require(["dojo/on","dojo/dom","dojo/dom-style","dojo/mouse","dojo/domReady!"],function (on,dom,domStyle,mouse) {
var myButton=dom.byId("myButton"),
myDiv=dom.byId("myDiv");
on(myButton,"click",function (evt) {
domStyle.set(myDiv,"backgrondColor","blue");
});
on(myDiv,mouse.enter,function (evt) {
domStyle.set(myDiv,"backgrondColor","red");
});
on(myDiv,mouse.leave,function (evt) {
domStyle.set(myDiv,"backgrondColor","");
});
});
②:Dojo的移除事件处理的方法,就是 handle.remove。on 的返回值是带有 remove 方法的简单对象,当调用 remove 的方法时,将移除事件监听器。例如触发一次事件,代码如下:
var handle=on(myButton,"click",function (evt) {
// 移除时间监听器
handle.remove();
alert("This alert will only happen one time.")
})
dojo 还可以用于事件委托,可以使用 dojo/on 来处理自定义事件,代码如下:
// 自定义事件
on(this,"onShowPanel",frame,"selectPanel")
上面的代码表示当调用 _BaseWildget 类的 onShowPanel 时,同时触发 frame (小部件框架)的 selectPanel。
③ map.on('extent-change',show)
代码解释:
为了处理一个事件,你需要添加监听它的代码。为一个事件注册一个监听器可以让你的应用程序处于警告状态,以便在发生特定事件时需要做某些事情。具体来说,它将调用处理函数来响应事件。就像上面的代码中的 show 函数。
④ registry.byId().on():
代码:
registry.byId("addNums").on("click",function(){
// 代码写在这里
});
代码解释:获取 id 为 addNums 的元素,然后添加 click 函数,函数里面执行相应的操作。
例如我们需要给一个 id 为 layerInfo 的按钮,添加显示图层信息的函数 showLayerInfos。代码如下:
registry.byId("layerInfo").on("click", showLayerInfos);
function getLayerJson(url, id) {
script.get(url + "/" + id + "/?f=json", {
jsonp: "callback"
}).then(function (data) {
setLayerExtent(data);
}, function (err) {
console.log(err);
return err;
});
};
⑤map.on('load', setupNavBar)
就是通过地图的 on 事件,随着地图的加载,执行函数 setupNavBar。
⑥map.on('mouse-move', showCoordinates); 鼠标移动触发事件 showCoordinates, map.on('mouse-drag', showCoordinates);
在鼠标被拖动时触发,直到鼠标按钮被释放。
可以参考官方给出的 API参考
⑦dom.byId
与 registry.byId
的区别:dom.byId
跟 dojo.byId
获取到的就是普通的HTMl文档结构树中的某个结点元素,以下简称dom结点, 而 registry.byId
获取到的是一个dojo 的widget,以下简称widget结点。它们的区别之一是 innerHTML, tagName 等方法只对用 dom结点生效。
。说白了就是registry.byId()
是获取通过dijit 类渲染的元素的ID
而dom.byId
就是获取普通的HTMl文档结构树中的某个结点元素。
4. 选择元素
在 dojo 中,有两种选择元素的方法,分别是 dojo/dom::byId() (替换 dojo.byId)和 dojo/query (替换 dojo.query),这两个的区别就是,byId 返回一个元素,而 query 返回数组。一般我们使用 query 方法较多。
在 dojo 中,可以通过如下方法来选择元素。
(1)根据 ID 来选择
例如可使用如下代码选择 ID 为 “node” 的超链接:
require(["dojo/dom"],function (dom) {
var node=dom.byId("node");
})
或者使用 dojo/query 方法如下代码:
require(["dojo/query"],function (query) {
query("#node"); //这里为# 符号,跟css id选择器一样
});
两种方法执行的效果是一样的,第一段代码返回一个元素,第二段代码返回含有一个元素的数组。
(2)根据类型选择
例如可以使用如下代码选择所有的 a 元素:
arr=query('a');
(3)根据样式名选择
例如可以使用如下代码选择所有样式为 myDiv 的元素:
arr=query(".myDiv");//这里是 . 符号
(4)可选择第一个指定类型
例如可以使用如下代码选择第一个超链接元素:
arr=query('a:first-child');
(5)选择指定节点下的所有元素(包括间接子元素)
例如可以使用如下代码选择 "sub_1"下的所有超链接元素:
arr=query("a","sub_1");
或者:
arr=query('#sub_1 a');
或者:
arr=query('div#sub_1 a');
第三种方法。不但指定了父节点 ID 为 “sub_1” ,还指定父节点类型为 div。
(6)选择直接子元素
例如可以使用如下代码在指定节点 "sub_1" 的直接子元素中,选择所有超链接元素:
arr=query('> a',"sub_1");//大于后面要有空格
或者:
arr=query('#sub_1 > a');//大于号后面要有空格
或者:
arr=query('div#sub_1 > a');//大于号后面要有空格
这里的“>”大于号代表直接子元素。
(7)根据元素的属性选择
例如可以使用如下代码选择 ID 属性值等于“a2”的元素:
arr=query('a[id=a2]');
还有其他判断方法:
- element[attr="bar"] :属性值等于“bar”。
- element[attr!="bar"]:属性值等于“bar”。
- element[attr^="bar"]:属性值等于“bar”。
- element[attr$="bar"]:属性值等于“bar”。
- element[attr~="bar"]:属性值等于“bar”。
- element[attr*="bar"]:属性值等于“bar”。
(8)选择第 n 个元素
例如:
arr=query('a:nth-child');
或者:
arr=query('> a:nth-child(1)');
第一种是全部的超链接元素,第二种是直接的子超链接元素。
(9)选择奇(偶)元素
例如:
arr=query('a:nth-child(even)');
或者:
arr=query('> a:nth-child(even');
5. 代码的优化
在将一个图形加入到地图的图形图层之前,最好是设置图形的几何对象与符号。如果在地图中加入了一个图形,然后再调用该图形的 setGeometry 或 setSymbol 方法将强迫该图形重画,下面的代码效率较低:
var graphic=new Graphic(geometry,defaultSymbol);
map.graphics.add(graphic);
if(isSelected)
{
graphic.setSymbol(highlightSymbol);
}
应该使用下面的代码:
var graphic=new Graphic(geometry,isSelected ? highlightSymbol:defaultSymbol);
map.graphics.add(graphic);
在创建符号对象时,应该使用默认的符号构造函数,并只覆盖那些要自定义的属性,因此,需要我们在创建符号对象之前,首先检查每种符号的默认属性。
例如,对于线符号来说,默认是实线,但下面的代码通过设置所有的属性来创建一个线符号,就会带来效率的问题。
var symbol=new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,new Color([255,0,0]),1);
下面的代码效率相对较高,因为它覆盖了需要定义的颜色属性:
var symbol=new SimpleLineSymbol().setColor(new Color([255,0,0]));
可以通过方法链的方式可以减少代码行,图形对象以及符号对象的设置方法返回的是自身对象,因此可以使用方法链,下面的代码效率相对要低:
var su=symbol=new SimpleMarkerSymbol();
symbol.setSize(10);
symbol.setColor(new Color([255,0,0]));
下面的代码效率更高:
var symbol=new SimpleMarkerSymbol().setSize(10).setColor([255,0,0]);
5. 相关知识
下面的代码:
var fieldLayer = new esri.layers.FeatureLayer("https://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Petroleum/KSPetro/MapServer/1", {
mode: esri.layers.FeatureLayer.MODE_SNAPSHOT
});
fieldLayer.setDefinitionExpression("FIELD_NAME = 'ARROYO'");
map.addLayer(fieldLayer);
其中上面的mode: esri.layers.FeatureLayer.MODE_SNAPSHOT
是设置加载要素的显示模式,这里设置显示模式为快照模式。
这句代码fieldLayer.setDefinitionExpression("FIELD_NAME = 'ARROYO'");
是通过FeatureLayer
类的setDefinitionExpression
方法设置一个定义表达式,以便获取满足定义表达式的要素。还可以通过FeatureLayer
类的setTimeDefinition
方法获取指定时间范围内的要素。不过该方法只对时间感知型图层起作用,而且显示模式必须为快照模式。