<\/HEAD>
<\/P>
Vor einiger Zeit habe ich einen Artikel darüber geschrieben, wie man Embrace your AMD modules<\/A>. Einige Fragen tauchten auf, als Beispiele gezeigt wurden, wie man dies mit Best Practices und empfohlenen Arbeitsweisen für Module macht. Also dachte ich, ich helfe heute dabei.<\/P><\/P>
Ich habe ein
Beispiel aus der Dokumentation<\/A> genommen, das ich vor einiger Zeit aktualisiert habe, um einige Funktionen hinzuzufügen<\/A>.<\/P><\/P>
Ich wollte überlegen, wie ich das in eine modularere App mit AMD aufteilen könnte.<\/P>
<\/P>
Zuerst schauen wir uns den Code an und ignorieren vorerst das HTML.<\/P>
require([
"esri\/Color", "esri\/dijit\/PopupTemplate", "esri\/layers\/FeatureLayer", "esri\/map", "esri\/renderers\/BlendRenderer",
"esri\/symbols\/SimpleFillSymbol", "esri\/symbols\/SimpleLineSymbol", "dojo\/on", "dojo\/domReady!"
], function (Color, PopupTemplate, FeatureLayer, Map, BlendRenderer, SimpleFillSymbol, SimpleLineSymbol, on){
map = new Map("map", {
basemap: "topo",
center: [-118.40, 34.06],
zoom: 15
});
\/\/-Setze die Parameter des blendRenderer
var blendRendererParams = {
\/\/-blendMode:"overlay" \/\/-Standardmäßig wird "source-over" verwendet, zum Anzeigen eines anderen Modus auskommentieren
\/\/-Siehe: <\/SPAN>
https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/CanvasRenderingContext2D\/globalCompositeOperation<\/A>
symbol: new SimpleFillSymbol().setOutline(new SimpleLineSymbol().setWidth(0)),
fields: [
{
field: "OWNER_CY",
label: "Eigentümer bewohnt",
color: new Color([0, 0, 255])
}, {
field: "RENTER_CY",
label: "Mieter bewohnt",
color: new Color([255, 0, 0])
}, {
field: "VACANT_CY",
label: "Leerstehend",
color: new Color([0, 255, 0])
}
],
opacityStops: [
{
 :& nbsp:& nbsp:& nbsp:& nbsp:& nbsp:& nbsp:value: 0.1,
 :& nbsp:& nbsp:& nbsp:& nbsp:& nbsp:& nbsp:opacity: 0
 :& nbsp:& nbsp:& nbsp:& nbsp;},
 :& nbsp:& nbsp:& nbsp:& nbsp:{
 :& nbsp:& nbsp:& nbsp:& nbsp:value: 1,
 :& nbsp:& nbsp:& nbsp:& nbsp:opacity: 0.7
 :& nbsp:& nbsp:& nbsp;}
&nb sp ;& nb sp ;],
&nb sp ;normalizationField : "TOTHU_CY"
};
//Erstelle die PopupTemplate zur Anzeige von demografischen Informationen
var template = new PopupTemplate({
'title': 'Wohnstatus nach Census-Block',
'tfieldInfos': [
{
'tfieldName': 'OWNER_CY',
'tlabel': 'Anzahl der eigentümerbewohnten Häuser',
'tvisible': true,
'tformat': {
'tplaces': 0,
'tdigitSeparator': true
}
}, {
'tfieldName': 'RENTER_CY',
'tlabel': 'Anzahl der mieterbewohnten Häuser',
'tvisible': true,
'tformat': {
'tplaces': 0,
'tdigitSeparator': true
}
}, {
'tfieldName': 'VACANT_CY',
'tlabel': 'Anzahl der leerstehenden Häuser',
'tvisible': true,
'tformat': {
'tplaces': 0,
'tdigitSeparator': true
}
}, {
'tfieldName': 'TOTHU_CY',
'tlabel': 'Gesamtzahl der Wohneinheiten',
'tvisible': true,
'tformat': {
'tplaces': 0,
'tdigitSeparator': true
}
}
]
});
& nb sp ;var layerUrl = "< /SPAN >< A class = "jive-link-external-small" href = "https://community.esri.com/external-link.jspa?url=http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Blocks near Wilshire enriched with Key Facts/FeatureServer/0" target = "_blank">http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Blocks near Wilshire enriched with Key Facts/FeatureServer/0";< /SPAN>
var renderer = new BlendRenderer(blendRendererParams);
layer = new FeatureLayer(layerUrl, {
id: "blendedLayer",
outFields: ["TOTHU_CY", "RENTER_CY", "OWNER_CY", "VACANT_CY"],
opacity: 1,
definitionExpression: "TOTHU_CY > 0",
infoTemplate: template
});
layer.setRenderer(renderer);
map.addLayer(layer);
on(document.getElementById("blendSelect"), "change", function(e) {
renderer.setBlendMode(e.target.value);
layer.redraw();
});
});< /PRE >< P > Das ist für eine kleine App nicht so schlimm, aber ich denke gerne darüber nach wie kann ich meine App skalieren?< /EM> Wo kann ich sie etwas aufteilen und was passiert genau?< /EM >< /P >< P >< /P >< P >< SPAN style = "color: #e23d39;" >< STRONG >< EM >Warnung - Das ist nur meine Meinung dazu, wie man diese App modularisieren könnte, andere haben vielleicht andere Meinungen.< /EM >< /STRONG >< /SPAN >< /P >< P >< /P >< H2 id = "toc-hId-1824765954" id = "toc-hId-1824765954" > Schritt für Schritt < /H2 >< P > Zunächst verwendet diese App den BlendRenderer, den ich hier< /A> besprochen habe. Das bringt mich auf die Idee, dass ich wahrscheinlich all diese Funktionalität auslagern könnte. Ich erstelle auch ein PopupTemplate< /A> und den BlendRenderer< /A> direkt in dieser einzigen Datei. Wenn ich solche Sachen sehe, die eher einfache Parameter sind, neige ich dazu, sie in Utility-Module zu packen, damit sie in mehreren Modulen leicht wiederverwendet werden können und Teil eines gemeinsamen Kerns meiner Anwendung sind.< /P >< P >< /P >< P > Also kann ich sie in eigene Utility-Module auslagern, die Sie in diesem Beispiel-Repository sehen können.< /A> < /P >< P >< /P >< P > Ok, das war ziemlich einfach, nur kopieren/einfügen in ein paar Module. Jetzt denken wir darüber nach, was meine App macht. Der Einfachheit halber sagen wir mal, dass ich mich darauf konzentriere, einige Bevölkerungsinformationen zu visualisieren. Konzentrieren wir das in einem Widget. Dieses Widget könnte ungefähr so aussehen:< /P >< P >< /P >< PRE class = "lia-code-sample line-numbers language-none" > define([
' dojo\/_base\declare ',
't dojo\/_base\lang ',
't dojo\/_topic ',
't dijit\/_WidgetBase ',
't dijit\/_TemplatedMixin ',
't esri\/_layers\FeatureLayer ',
't dojo\/_text!.\widget.html '
], function(
declare , lang , topic ,
_WidgetBase , _TemplatedMixin ,
FeatureLayer ,
templateString
) {
vart hitch = lang.hitch;
return declare([_WidgetBase , _TemplatedMixin ], {
templateString : templateString ,
baseClass : 'population-info' ,
postCreate : function() {
vart layerOptions = this.get('layerOptions');
vart renderer = this.get('renderer');
vart url = this.get('url');
vart map = this.get('map');
vart layer = new FeatureLayer(url , layerOptions);
layer.setRenderer(renderer);
map.addLayer(layer);
this.set('layer' , layer);
th is.own( // mache dies damit das Widget Speicher bereinigen kann wenn es zerstört wird
topic.subscribe('blend-select-update', hitch(this, 'updateBlendMode'))
);
},
updateBlendMode: function(mode) {
console.log('update blend mode with dojo/topic');
var layer = this.get('layer');
var renderer = this.get('renderer');
renderer.blendMode = mode;
layer.setRenderer(renderer);
layer.refresh();
}
});
});Dies ist ein ziemlich einfaches Widget. Wir verwenden eine postCreate-Methode, um Dinge einzurichten.
Ich spreche in diesem Video über den dijit-Lebenszyklus. In dieser Methode richte ich meine Ebene ein und weise den Renderer zu, der in den Optionen übergeben wurde. Es gibt eine einfache HTML-Vorlage, die nur eine Kopie des HTML aus dem Beispiel ist, das eine Beschreibung der Daten enthält. Ich verwende auch dojo/topic, über das ich hier gesprochen habe. Ich werde einige verschiedene Methoden der Widget-Kommunikation demonstrieren, eine mit dojo/topic und eine mit dojo/Evented.
Dieses Modul hat auch eine updateBlendMode-Methode, die einfach das dojo/topic-Subscribe behandelt und den blendMode aktualisiert. Das bedeutet, dass jedes Modul in Ihrer Anwendung ein Update für den blendMode veröffentlichen kann oder aus welchem Grund auch immer. Meiner Meinung nach ist dies die ideale Methode der Widget-Kommunikation, da die einzelnen Widgets nichts voneinander wissen müssen.
Das andere im Beispiel war ein Auswahlmenü, mit dem Sie den blendMode aktualisieren konnten. Auch hier denke ich, dass dies der perfekte Kandidat für ein weiteres Widget ist. Der Code für dieses Widget könnte ungefähr so aussehen:
define([
'dojo/_base/declare',
'dojo/Evented',
'dojo/topic',
'dijit/_WidgetBase',
'dijit/_TemplatedMixin',
'dojo/text!./widget.html'
], function(
declare, Evented, topic,
_WidgetBase, _TemplatedMixin,
templateString
) {
return declare([_WidgetBase, _TemplatedMixin, Evented], {
templateString: templateString,
baseClass: 'blend-select',
onChange: function(e) {
var val = e.target.value;
if (this.cboxNode.checked) {
topic.publish('blend-select-update', val);
} else {
this.emit('blend-select-update', val);
}
}
});
})
Dieses Widget verwendet dojo/Evented und dojo/topic. Sie werden bemerken, dass das Widget selbst dojo/Evented erweitert und dabei dojo/_base/declare verwendet. Dies ermöglicht es Ihnen, this.emit() zu verwenden, um Ereignisse von Ihrem Widget auszusenden. Dieses Widget hat das Auswahlmenü für blendModes und auch ein Kontrollkästchen, um festzulegen, ob Sie ein Ereignis mit dem neuen blendMode senden oder den blendMode über dojo/topic veröffentlichen möchten.
Die Vorlage dafür sieht so aus:
<div>
<div>
<input type="checkbox" data-dojo-attach-point="cboxNode"> Verwende dojo/topic
</div>
<select data-dojo-attach-event="change:onChange">
<option value="source-over">source-over</option>
<option value="source-in">source-in</option>
<option value="source-out">source-out</option>
<option value="source-atop">source-atop</option>
<option value="destination-over">destination-over</option>
<option value="destination-in">destination-in</option>
<option value="destination-out">destination-out</option>
<option value="destination-atop">destination-atop</option>
<option value="lighter">{lighter}</option>
<option value="copy">{copy}</option>
<option value="xor">{xor}</option>
<option value="overlay">{overlay}</option>
<option value="normal">{normal}</option>
<option value="multiply">{multiply}</option>
<option value="screen">{screen}</option>
<option value="darken">{darken}</option>
<option value="lighten">{lighten}</option>
<option value="color-dodge">color-dodge</option>
<option value="color-burn">color-burn</option>
<option value="hard-light">{hard-light}</option>
<option value="soft-light">{soft-light}</option>
  < option value= "difference "> {difference} & lt / option >
wenn Dojo geladen wird. Sie können die Dokumentation hier einsehen. Das macht meine eigentliche index.html-Datei wirklich einfach.<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
<title>Modular App Demo</title>
<link rel="stylesheet" href="http://js.arcgis.com/3.14/esri/css/esri.css">
<link rel="stylesheet" href="css/main.css">
<script src="dojoConfig.js"></script>
</head>
<body>
<div id="blend-selection-container"></div>
<div id="population-container"></div>
<div id="map"></div>
<script src="http://js.arcgis.com/3.14/"></script>
</body>
</html>
Sie können über andere Methoden zur Initialisierung Ihrer Anwendung hier lesen.
Nehmen Sie es Stück für Stück
Die gesamte modularisierte Anwendung finden Sie in diesem github repo. Ich hoffe, dies gibt Ihnen einen besseren Einblick, wie Sie eine Anwendung in Module aufteilen können und wie Sie Modularität in Ihrer eigenen Entwicklung betrachten können. Ich neige dazu, Funktionen einer Anwendung in eigene Widgets aufzuteilen, sei es Bearbeitung, Suche, Geocodierung oder sogar nur einige Verhaltensweisen hinzuzufügen.
Sie können einige weitere Beispiele für Modularität in Projekten sehen, an denen ich in der Vergangenheit gearbeitet habe, in diesem starter-kit, das vollständig konfigurierbar ist, oder meine neuesten Experimente in diesem yeoman generator, und sample app. Eine weitere sehr modulare App ist zum Beispiel die cmv app.
Noch einmal, dies ist einfach meine Meinung darüber, wie ich denke, dass man eine App in kleinere Module aufteilen kann, die es nicht nur einfacher machen, sie im Laufe der Zeit zu warten, sondern auch neue Funktionalitäten leicht hinzuzufügen.
Für mehr geodev Tipps und Tricks, schauen Sie sich meinen Blog an.