Codieren einfacher Apps
In diesem Thema wird die Struktur einer einfachen App vorgestellt, und es werden einige der Codierungskonventionen für Windows Store-Apps mit JavaScript erläutert.
Voraussetzungen
Es wird vorausgesetzt, dass Sie wie unter Erstellen Ihrer ersten Windows Store-App mit JavaScript beschrieben eine einfache Windows Store-App mit JavaScript erstellen können.
Inhalt einer einfachen App
Wenn Sie mit Microsoft Visual Studio Express 2012 für Windows 8 ein neues Projekt mit der Vorlage Leere Anwendung erstellen, wird eine App erstellt, die mehrere Dateien enthält:
- default.html
Die Startseite der App. Diese Seite wird angezeigt, wenn die App gestartet wird. Die Datei enthält Verweise auf "default.js", die Windows-Bibliothek für JavaScript-Dateien und -Formatvorlagen, und die Formatvorlage der App, "default.css".
- /js/default.js
JavaScript-Code, der das Verhalten der App beim Start festlegt. Die Datei enthält Code zum Behandeln des Lebenszyklus der App. Die aus der Vorlage generierte Datei "default.js" behandelt die App-Aktivierung, eine typische App behandelt aber auch das Anhalten und Fortsetzen.
- /css/default.css
Die Cascading Stylesheet (CSS)-Formatvorlagen. Hier können Sie eigene Formatvorlagen definieren oder vorhandene Formatvorlagen der Windows-Bibliothek für JavaScript überschreiben. In der Standardimplementierung wird für das Body-Element ein Rasterlayout verwendet. Weitere Informationen zur Verwendung des Rasterlayouts finden Sie unter Rasterausrichtung.
- /References/Windows Library for JavaScript SDK
Die Windows-Bibliothek für JavaScript, ein Satz von Formatvorlagen, Steuerelementen und Hilfsprogrammen zum Erstellen von Apps.
- package.appmanifest
Das App-Manifest. Diese Datei listet den Inhalt der App auf und beschreibt ihre Funktionen, z. B. ob die App auf die Webcam des Benutzers zugreifen kann. In dieser Datei wird auch festgelegt, welche Seite als Startseite der App verwendet werden soll. Wenn Sie Visual Studio Express 2012 für Windows 8 verwenden, um Ihrer App weitere Dateien hinzuzufügen, wird das App-Manifest automatisch aktualisiert.
- /images
Die Vorlage enthält auch mehrere Bilddateien, z. B. "splashscreen.png" für das Bild des Begrüßungsbildschirms und die Bilddatei "storelogo.png", die für Windows Store verwendet wird.
Dateien "default.html" und "default.js"
Unabhängig davon, mit welcher Vorlage von Visual Studio Express 2012 für Windows 8 Sie Ihre Windows Store-App mit JavaScript erstellen, enthält die App die Datei "default.html" und die Datei "default.js".
Im Folgenden sehen Sie das Markup für "default.html", das beim Erstellen eines neuen Projekts mit der Vorlage Leere Anwendung generiert wird.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>BasicAppExample</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.1.0.RC/css/ui-dark.css" rel="stylesheet"> <script src="//Microsoft.WinJS.1.0.RC/js/base.js"></script> <script src="//Microsoft.WinJS.1.0.RC/js/ui.js"></script> <!-- BasicAppExample references --> <link href="/css/default.css" rel="stylesheet" /> <script src="/js/default.js"></script> </head> <body> <p>Content goes here</p> </body> </html>
Im Folgenden sehen Sie den beim Erstellen eines neuen Projekts automatisch generierten Code für die Datei "default.js".
(function () { "use strict"; WinJS.Binding.optimizeBindingReferences = true; var app = WinJS.Application; var activation = Windows.ApplicationModel.Activation; app.onactivated = function (args) { if (args.detail.kind === activation.ActivationKind.launch) { if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) { // TODO: This application has been newly launched. Initialize // your application here. } else { // TODO: This application has been reactivated from suspension. // Restore application state here. } args.setPromise(WinJS.UI.processAll()); } }; app.oncheckpoint = function (args) { // TODO: This application is about to be suspended. Save any state // that needs to persist across suspensions here. You might use the // WinJS.Application.sessionState object, which is automatically // saved and restored across suspension. If you need to complete an // asynchronous operation before your application is suspended, call // args.setPromise(). }; app.start(); })();
App-Lebenszyklus
Der Großteil des Codes in der Datei "default.js" dient zum Behandeln des App-Lebenszyklus. Der App-Lebenszyklus beginnt mit dem Start der App und endet mit ihrem Schließen. Die Projektvorlagen enthalten ein allgemeines Muster für die Verwaltung des App-Lebenszyklus.
Der von der Vorlage generierte Code überprüft, ob die App über die Startseite gestartet wurde, und ruft WinJS.UI.processAll auf. Die WinJS.UI.processAll-Methode lädt alle Steuerelemente der Windows-Bibliothek für JavaScript, die Sie in der HTML-Datei deklariert haben. Falls Sie Code haben, der ausgeführt werden muss, wenn die App ihren Anfangszustand einrichtet, sollten Sie diesen Code in den Handler für das activated-Ereignis einfügen.
Hinweis Wenn während der Aktivierung viele Vorgänge ausgeführt werden, entsteht für den Benutzer der Eindruck, dass die App nicht reagiert. Führen Sie speicherintensive Vorgänge nach Möglichkeit nach dem Laden der App aus.
Die Vorlage enthält keinen Code, um das Anhalten, Fortsetzen oder Beenden der App zu behandeln. Weitere Informationen zum Behandeln dieser Zustände finden Sie unter App-Lebenszyklus.
Anonyme Funktionen und Strict-Modus
Wenn Sie daran gewöhnt sind, Websites zu programmieren, werden Ihnen einige Teile des Codes ungewohnt vorkommen. Zum einen ist die gesamte Datei in einer anonymen Funktion umschlossen:
(function () {
...
})();
Weshalb? In JavaScript gibt es zwei Bereiche: den globalen Bereich und den lokalen Bereich. Wenn Sie eine Variable außerhalb einer Funktionsdefinition deklarieren, ist sie eine globale Variable, und ihr Wert ist in der gesamten App zugreifbar und änderbar. Wenn Sie eine Variable innerhalb einer Funktionsdefinition deklarieren, ist sie eine lokale Variable. Außerhalb der Funktion kann nicht auf sie zugegriffen werden.
Durch das Umschließen des Codes in einer anonymen Funktion wird der Code privat. Diese Codiertechnik wird empfohlen, da dadurch der Bereich des Codes eingeschränkt wird und "Verunreinigungen" des globales Namespaces vermieden werden. Zudem lassen sich Namenskonflikte oder versehentliche Änderungen von Werten so leichter vermeiden.
Hauptsächlich dienen anonyme Funktionen zum Erstellen privater Member in der Programmiersprache JavaScript, in der private Member andernfalls nicht unterstützt werden.
Falls Sie sich fragen, wozu die zusätzliche Klammer am Ende der Funktionsdeklaration dient – sie ruft die anonyme Funktion auf:
(function () { ... })(); // Makes the function self-invoking.
Die Datei "default.js" deklariert außerdem die Ausführung im Strict-Modus:
(function () { "use strict"; // Declares strict mode. ... })();
Der Strict-Modus bietet eine bessere Fehlerprüfung für den JavaScript-Code. Wenn Sie den strict-Modus verwenden, gelten striktere Einschränkungen für den Code, als dies bei JavaScript normalerweise der Fall ist. Es ist z. B. nicht möglich, eine Variable zu verwenden, ohne sie zu deklarieren, in eine schreibgeschützte Eigenschaft zu schreiben oder eine with-Anweisung zu verwenden. Diese Einschränkungen helfen Ihnen dabei, besseren Code zu schreiben, und reduzieren die Wahrscheinlichkeit, dass sich Fehler in Ihre App einschleichen. Weitere Informationen zum strict-Modus finden Sie unter "Strict-Modus" in der JavaScript-Programmiersprachenreferenz
Hinzufügen von Ereignishandlern
Das Umschließen des Codes in einer anonymen Funktion bietet viele Vorteile, es zwingt Sie aber auch, Ihren Code anders als gewohnt zu schreiben. Ereignisse müssen z. B. anders behandelt werden.
Angenommen, Sie fügen der Seite "default.html" eine Schaltfläche hinzu. Wenn der Benutzer auf die Schaltfläche klickt, sollen die X- und Y-Koordinaten des Punkts angezeigt werden, auf den der Benutzer geklickt hat. Zum Anzeigen dieser Informationen fügen Sie ein Absatzelement hinzu. Im nächsten Beispiel werden diese Elemente der Datei "default.html" hinzugefügt, und es wird ein div-Element hinzugefügt, das die Elemente enthält. (Die Eigenschaften -ms-grid-row und -ms-grid-column des div-Elements werden festgelegt, weil das body-Element die Formatvorlage -ms-grid display verwendet.)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>BasicAppExample</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.1.0.RC/css/ui-dark.css" rel="stylesheet"> <script src="//Microsoft.WinJS.1.0.RC/js/base.js"></script> <script src="//Microsoft.WinJS.1.0.RC/js/ui.js"></script> <!-- BasicAppExample references --> <link href="/css/default.css" rel="stylesheet" /> <script src="/js/default.js"></script> </head> <body> <button id="button1">An HTML button</button> <p id="button1Output"></p> </body> </html>
Jetzt definieren Sie in der Datei "default.js" einen Ereignishandler für das click-Ereignis der Schaltfläche. Die meisten Ereignishandler empfangen ein einzelnes Argument, ein Event-Objekt, das Informationen zum Ereignis enthält. Andere Ereignisse geben möglicherweise andere Typen von Ereignisinformationsobjekten zurück, die spezifische Informationen für das Ereignis enthalten.
Das click-Ereignis stellt ein MouseEvent-Objekt bereit, das Informationen zum Ereignis enthält, z. B. welche Maustaste gedrückt wurde und von welchem Objekt das Ereignis ausgelöst wurde. In diesem Beispiel wird ein click-Ereignishandler erstellt, der die X- und Y-Koordinaten des Punkts, auf den der Benutzer geklickt hat, mit dem MouseEvent-Objekt abruft.
(Das click-Ereignis reagiert auch auf Finger- und Tastatureingaben. In den Beispielen in diesem Thema wird davon ausgegangen, dass der Benutzer mit einer Maus klickt. Weitere Informationen zur Interaktion mit Fingereingaben und anderen Geräten finden Sie unter Reaktion auf Benutzerinteraktionen.)
(function () { "use strict"; WinJS.Binding.optimizeBindingReferences = true; var app = WinJS.Application; var activation = Windows.ApplicationModel.Activation; app.onactivated = function (args) { if (args.detail.kind === activation.ActivationKind.launch) { if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) { // TODO: This application has been newly launched. Initialize // your application here. } else { // TODO: This application has been reactivated from suspension. // Restore application state here. } args.setPromise(WinJS.UI.processAll()); } }; app.oncheckpoint = function (args) { // TODO: This application is about to be suspended. Save any state // that needs to persist across suspensions here. You might use the // WinJS.Application.sessionState object, which is automatically // saved and restored across suspension. If you need to complete an // asynchronous operation before your application is suspended, call // args.setPromise(). }; // The click event handler for button1 function button1Click(mouseEvent) { var button1Output = document.getElementById("button1Output"); button1Output.innerText = mouseEvent.type + ": (" + mouseEvent.clientX + "," + mouseEvent.clientY + ")"; } app.start(); })();
Jetzt müssen Sie nur noch den Ereignishandler für die Schaltfläche registrieren. Möglicherweise möchten Sie den Handler registrieren, indem Sie das onclick-Attribut der Schaltfläche festlegen.
<button id="button1" onclick="button1Click(event)">An HTML button</button>
Dies funktioniert hier aber nicht. Wenn Sie die App ausführen und auf die Schaltfläche klicken, wird die folgende Ausnahme angezeigt:
-
Unhandled exception at line 21, column 39 in ms-appx://77d9a962-d259-45b1-9f04-3abf289aff57-6mtxa77c2r4nt/default.html
0x800a1391 - JavaScript runtime error: 'button1Click' is undefined
Die Datei "default.js" enthält aber eine Definition für "button1Click". Warum funktioniert es also nicht?
Der Grund für diesen Fehler ist, dass der gesamte Code in der anonymen Funktion in "default.js" lokal bzw. privat ist. Die Datei "default.html" kann nicht auf die button1Click-Funktion zugreifen.
(function () { // default.html can't access anything inside this function. })();
Sie haben zwei Möglichkeiten, diese Einschränkung zu umgehen. Sie können button1Click öffentlich zugreifbar machen oder den Ereignishandler im Code anfügen. Die empfohlene Methode ist das Anfügen des Ereignishandlers im Code, im Folgenden werden aber beide Ansätze erläutert. (Wenn Sie direkt zur empfohlenen Methode springen möchten, fahren Sie mit Anfügen eines Ereignishandlers im Code fort.)
Festlegen eines Members als öffentlich zugreifbar
Jede Windows Store-App mit JavaScript enthält die Windows-Bibliothek für JavaScript. Einer der Vorteile der Windows-Bibliothek für JavaScript ist, dass sie die Möglichkeit bietet, Namespaces und Klassen zu definieren. Die WinJS.Namespace.define-Funktion erstellt einen öffentlichen Namespace. Die Funktion hat zwei Parameter: den Namen des zu erstellenden Namespaces und ein Objekt, das ein oder mehrere Eigenschaft/Wert-Paare enthält. Jede Eigenschaft ist der öffentliche Name des Members, und jeder Wert ist eine Variable, Eigenschaft oder Funktion, die verfügbar gemacht werden soll.
In diesem Beispiel wird ein Namespace mit dem Namen "startPage" erstellt, der einen einzelnen Member namens clickEventHandler enthält. Der Wert von clickEventHandler ist die zuvor definierte button1Click-Funktion.
var namespacePublicMembers = { clickEventHandler: button1Click };
WinJS.Namespace.define("startPage", namespacePublicMembers);
Im Folgenden sehen Sie die vollständige Datei "default.js", die zeigt, wie sich die Namespacedeklaration in den Rest der Datei einfügt.
(function () { "use strict"; WinJS.Binding.optimizeBindingReferences = true; var app = WinJS.Application; var activation = Windows.ApplicationModel.Activation; app.onactivated = function (args) { if (args.detail.kind === activation.ActivationKind.launch) { if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) { // TODO: This application has been newly launched. Initialize // your application here. } else { // TODO: This application has been reactivated from suspension. // Restore application state here. } args.setPromise(WinJS.UI.processAll()); } }; app.oncheckpoint = function (args) { // TODO: This application is about to be suspended. Save any state // that needs to persist across suspensions here. You might use the // WinJS.Application.sessionState object, which is automatically // saved and restored across suspension. If you need to complete an // asynchronous operation before your application is suspended, call // args.setPromise(). }; // The click event handler for button1 function button1Click(mouseEvent) { var button1Output = document.getElementById("button1Output"); button1Output.innerText = mouseEvent.type + ": (" + mouseEvent.clientX + "," + mouseEvent.clientY + ")"; } var namespacePublicMembers = { clickEventHandler: button1Click }; WinJS.Namespace.define("startPage", namespacePublicMembers); app.start(); })();
Nachdem Sie den Ereignishandler nun als startPage.clickEventHandler öffentlich verfügbar gemacht haben, können Sie ihn zum Festlegen des onclick-Attributs der Schaltfläche verwenden.
<button id="button1" onclick="startPage.clickEventHandler(event)">An HTML button</button>
Wenn Sie die App jetzt ausführen, funktioniert der Ereignishandler einwandfrei.
Dies ist eine Möglichkeit zum Verbinden eines Ereignishandlers. Die andere Möglichkeit ist das Anfügen des Ereignishandlers im Code. Damit werden wir uns jetzt genauer befassen.
Anfügen eines Ereignishandlers im Code
Eine weitere Möglichkeit (die empfohlene Methode) zum Anfügen eines Ereignishandlers ist das Abrufen des Steuerelements mit JavaScript und anschließende Registrieren des Ereignisses mithilfe der addEventListener-Methode. Die Frage ist, wann Sie das Steuerelement abrufen sollten? Sie könnten es einfach an einer beliebigen Stelle im JavaScript-Code hinzufügen, dann bestünde allerdings die Möglichkeit, dass das Steuerelement aufgerufen wird, bevor es überhaupt vorhanden ist.
Für die meisten HTML-Dateien besteht die Lösung darin, eine then- oder done-Funktion für die von der WinJS.UI.processAll-Methode zurückgegebene Promise bereitzustellen. (Für Page-Steuerelemente können Sie stattdessen die ready-Funktion verwenden.)
Was ist eine Promise? Um das Reaktionsverhalten der App zu verbessern, werden viele Funktionen der Windows-Bibliothek für JavaScript und der Windows-Runtime asynchron ausgeführt. Auf diese Weise kann die App Vorgänge im Hintergrund ausführen und gleichzeitig weiter auf Benutzerinteraktionen reagieren. Anstatt direkt einen Wert zurückzugeben, gibt eine asynchrone Funktion eine Promise für einen Wert zurück. Weitere Informationen zur asynchronen Programmierung finden Sie unter Asynchrone Programmierung in JavaScript.
args.setPromise(WinJS.UI.processAll().then(function () {
var button1 = document.getElementById("button1");
button1.addEventListener("click", button1Click, false);
})
);
Hier sehen Sie den vollständigen Code für die Dateien "default.html" und "default.js":
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>BasicAppExample</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.1.0.RC/css/ui-dark.css" rel="stylesheet"> <script src="//Microsoft.WinJS.1.0.RC/js/base.js"></script> <script src="//Microsoft.WinJS.1.0.RC/js/ui.js"></script> <!-- BasicAppExample references --> <link href="/css/default.css" rel="stylesheet" /> <script src="/js/default.js"></script> </head> <body> <button id="button1">An HTML button</button> <p id="button1Output"></p> </body> </html>
(function () { "use strict"; WinJS.Binding.optimizeBindingReferences = true; var app = WinJS.Application; var activation = Windows.ApplicationModel.Activation; WinJS.strictProcessing(); app.onactivated = function (args) { if (args.detail.kind === activation.ActivationKind.launch) { if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) { // TODO: This application has been newly launched. Initialize // your application here. } else { // TODO: This application has been reactivated from suspension. // Restore application state here. } args.setPromise(WinJS.UI.processAll().then(function () { var button1 = document.getElementById("button1"); button1.addEventListener("click", button1Click, false); }) ); } }; app.oncheckpoint = function (args) { // TODO: This application is about to be suspended. Save any state // that needs to persist across suspensions here. You might use the // WinJS.Application.sessionState object, which is automatically // saved and restored across suspension. If you need to complete an // asynchronous operation before your application is suspended, call // args.setPromise(). }; // The click event handler for button1 function button1Click(mouseEvent) { var button1Output = document.getElementById("button1Output"); button1Output.innerText = mouseEvent.type + ": (" + mouseEvent.clientX + "," + mouseEvent.clientY + ")"; } var namespacePublicMembers = { clickEventHandler: button1Click }; WinJS.Namespace.define("startPage", namespacePublicMembers); app.start(); })();
Hinzufügen von Seiten und Navigieren zwischen Seiten
Die Vorlage Leere Anwendung eignet sich gut für sehr einfache Apps. Wenn Sie eine komplexere App erstellen, möchten Sie den Inhalt aber wahrscheinlich auf mehrere Dateien verteilen.
Eine herkömmliche Website kann aus einer Reihe von Seiten bestehen, zwischen denen Sie mithilfe von Links navigieren. Jede Seite enthält einen eigenen Satz von JavaScript-Funktionen und -Daten, einen neuen HTML-Satz für die Anzeige, Stilinformationen usw. Dieses Navigationsmodell wird als mehrseitige Navigation bezeichnet.
Anders als eine herkömmliche Website funktioniert eine Windows Store-App mit JavaScript am besten, wenn das Modell für Einzelseitennavigation verwendet wird. Bei diesem Modell verwenden Sie nur eine Seite für die App und laden bei Bedarf weitere Daten in diese Seite.
Dies bedeutet, dass die App die Seite "default.html" nie verlässt. Legen Sie immer die Dateien "default.html" und "default.js" als Startseite der App fest. Sie definieren die äußerste Benutzeroberfläche für die App (z. B. die AppBar) und behandeln den App-Lebenszyklus.
Aber wie laden Sie den Inhalt von anderen Seiten, wenn Sie die Seite "default.html" nie verlassen? Dafür stehen mehrere Methoden zur Auswahl.
- Sie können HtmlControl verwenden, um HTML-Inhalte von einer anderen Seite anzuzeigen, die keine Interaktivität beinhaltet (HtmlControl unterstützt das Laden von JavaScript nicht).
- Sie können ein PageControl erstellen und auf der Hauptseite anzeigen. Ein PageControl ist ein Satz von HTML, JavaScript und CSS, den Sie ähnlich wie andere Steuerelemente innerhalb einer anderen HTML-Seite anzeigen können. Weitere Informationen zum Erstellen von Page-Steuerelementen finden Sie unter Hinzufügen von Seitensteuerelementen.
- Sie können ein iframe-Steuerelement verwenden, um Inhalt von einer anderen Seite anzuzeigen. Dies ist die am wenigsten effiziente Methode, um Inhalt von einer anderen Seite zu integrieren, aber die einzige Möglichkeit, wenn Sie eine externe Webseite anzeigen möchten.
- Sie können auch DOM-Methoden verwenden, um Inhalt von anderen Seiten zu integrieren.
Weitere Informationen zur Navigation finden Sie unter Unterstützen der Navigation.
Auswählen der am besten geeigneten Vorlage
Die Vorlage Leere Anwendung enthält das absolute Minimum an Code, das zum Erstellen einer Windows Store-App mit JavaScript notwendig ist. Visual Studio Express 2012 für Windows 8 enthält mehrere Vorlagen, die je nach Verwendungszweck der App einen besseren Ausgangspunkt darstellen können. Ausführliche Informationen zu diesen Vorlagen finden Sie unter JavaScript-Projektvorlagen für Windows Store-Apps.
Beispiele
Laden Sie die Beispiele herunter, um mehr über die Funktionsweise typischer Apps zu erfahren:
Zusammenfassung und nächste Schritte
In diesem Thema haben Sie die Komponenten einer einfachen App kennen gelernt und erfahren, wie Sie mit den Codierungskonventionen für Windows Store-Apps mit JavaScript arbeiten. Im nächsten Thema, HTML, CSS und JavaScript – Features und Unterschiede, werden weitere Unterschiede zwischen der Codierung für eine Windows Store-App mit JavaScript und der Codierung für eine Website erläutert.
Verwandte Themen
- JavaScript-Projektvorlagen für Windows Store-Apps
- App-Lebenszyklus
- Schnellstart: Hinzufügen von HTML-Steuerelementen und Behandeln von Ereignissen
- Schnellstart: Hinzufügen von WinJS-Steuerelementen und -Stilen
- Unterstützen der Navigation
