Office 365 Platform Flexible Tools App Manifest Web Page HTML/CSS/JS App.
Windows Store Apps mit HTML & JS entwickeln
description
Transcript of Windows Store Apps mit HTML & JS entwickeln
Windows Store Apps mit
HTML & JS entwickelnChristian MoserSoftware Architekt und UX Designer, Zühlke
[email protected] | @christian_moser | wpftutorial.net
ZieleSie wissen wann HTML/JS/CSS die geeignete Entwicklungsplattform für eine App ist.Sie kennen die grundlegenden Konzepte einer JavaScript AppSie sind in der Lage selber eine einfache HTML/JS App zu entwickeln.
Agenda
Agenda1. HTML/JS als App-Sprachen2. Aufbau einer HTML/JS App3. Classes and Namespaces4. Application Lifecycle und State handling5. Pages und Navigation6. Controls7. DataBinding8. Model-View-ViewModel Pattern9. Windows Runtime10. Third-Party Libraries
HTML/JS als App-SprachenTeil 1
Motivation für HTML/JS als App-Sprachen? Sie haben bereits Erfahrung mit Web-Technologien Es bestehen bereits JavaScript-Komponenten Sie möchten Cross-Platform entwickeln Sie binden Services ein, die JSON-Daten liefern
(können) Sie sind heimlich verliebt in jQuery, require.js oder
knockout?
Typische “Smells” der Webentwicklung Jeder Browser interpretiert Standards
unterschiedlich HTML5 und CSS3 sind nur auf neusten Browsern
verfügbar JavaScript bietet out-of-the-box keine Konstrukte
für grössere Mengen Code (z.B. Klassen, Namespaces, Interfaces, Module)
JavaScript Performance ist schlecht auf älteren Browsern
Sandboxed (kein Dateizugriff, Office Integration,…)
Apps vs. Web-Pages
Diverse Browser
IE10 (mit all seinen Features)Multi- oder Single-
PageSingle-Page
Sandboxed Plattform-Zugriff (WinRT)jQuery, Knockout,
requireJSWinJS, jQuery, Knockout,
requireJS
AudioExplosion Demo - IE TestdriveAudioExplosionApp
Demo Audio Explosion
Aufbau einer HTML/JS AppTeil 2
WinJS
Unser Werkzeugkoffer
CSS 3 WinRT
HTML 5 JavaScript 5Visual StudioTemplates
Knockout,jQuery,require.js
Visual Studio TemplatesBlank Navigatio
nGridSplit Fixed
Leere App navigator.js,Home-Page
Grid-View, List-View,Sample Data
Grouped ListViewText-Wrapping
Fixed size inViewBox
Demo – Aufbau einer App
Application Lifecycle und StateTeil 3
App LifecycleActivation ReasonsLaunchedSecondary TileSearch targetShare targetProtocol activatedFile Save PickerFile Open PickerFile ActivatedCached File UpdateDevice activatedCamera SettingsPrint task
NotRunning
Running
Suspended
TerminatedSpeichermangel
Resumingin den Vordergrund
Suspending5s im Hintergrund
ActivatedCrashed
Application Objectvar app = WinJS.Application, webApp = Windows.UI.WebUI.WebUIApplication, activation = Windows.ApplicationModel.Activation;
Activatingapp.onactivated = function (e) { if (e.detail.kind === activation.ActivationKind.launch) { // Initialization }};
Suspendingapp.oncheckpoint = function (e) { // Save State and Navigation};
ResumingwebApp.addEventListener("resuming", function (e) { // Restore State and Navigation}, false);
State and History beibehalten
var app = WinJS.Application;var nav = WinJS.Navigation; app.oncheckpoint = function (e) { app.sessionState.history = nav.history; app.sessionState.myData = myData;};
webApp.addEventListener("resuming", function (e) { nav.history = app.sessionState.history; myData = app.sessionState.myData;};
WinJS.Application.sessionState
Objekte im SessioState müssen JSON serialisierbar sein.
Demo - Visual Studio Template
Pages und NavigationTeil 4
Page definition<div id="contenthost">
</div>
var host = document.getElementById('contentHost');WinJS.Pages.render("/pages/home/home.html", host);
WinJS.UI.Pages.define("/pages/home/home.html", { ready: function (element, options) { // Initialize page }});
Page 1
Navigationnavigator.js
WinJS.Pages.render()
WinJS.Navigation.onnavigating
WinJS.Navigation.back(1);
/pages/home/home.html
Page 1
WinJS.Navigation.navigate("/add/add.html");
/pages/add/add.html
Page 2
WinJS.Navigation.forward();
/pages/detail/detail.html
Page 3
ControlsTeil 5
Modern UI Controls
HTML5 Controls mit Win8-Styling
<button class="win-backbutton"></button>
<select> <option>Option 1</option> <option>Option 2</option> <option>Option 3</option></select>
<input type="range" class="win-vertical"/>
<progress class="win-ring win-large" />
WinJS Controls<div data-win-control="WinJS.UI.Rating" data-win-options="{averageRating:3, maxRating:8}"></div>
WinJS.UI.processAll(root);
<div data-win-control="WinJS.UI.AppBar"> <button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{label:'Add Album', icon:'add'}" > </button></div>
Styling von Controls
input[type=text]:hover::-ms-clear { background: purple;}
ControlTag
StatePseudo-Class
PartPseudo-Element
Liste aller WinJS-Control-PartsControl Partsinput [type = checkbox] -ms-checkinput [type = radio] -ms-checkinput [type = range] -ms-fill-lower, -ms-track,
-ms-fill-upper, -ms-thumb, -ms-ticks-after, -ms-ticks-before, -ms-ticks-on-track
input [type = email], input [type = search], input [type = tel], input [type = url]
-ms-value, -ms-clear
input [type = password] -ms-value, -ms-revealprogress -ms-fillselect -ms-value, -ms-expand
Classes and Namespaces
Teil 6
Closures(function() { "use strict";
// isolierter Code
})();
Self-executing anonymous function verhindert Nameskollisionen im globalen Namespace.
Klassen in WinJSvar MyClass = WinJS.Class.define(function() { // Constructor}, { // Members}, { // Static members});
var myObj = new MyClass();
var Person = WinJS.Class.define(function (firstname, lastname) { this._firstname = firstname; this._lastname = lastname; }, { fullName: { get: function () { return this.firstname + " " + this.lastname; } } }); var hans = new Person("Hans", "Muster");console.log(hans.FullName);
Private Members und Properties
Private Members Wenn Name mit Underscore (“_”) beginnt
Propertiesproperty: { get : function(){}, set : function(value){}}
Namespaces in WinJSWinJS.Namespace.define("Shape", { // Classes MyClass : WinJS.Class.define(function() {}),
// Functions myFunction : function() {},
// Values myValue: 5 }); var myInstance = new Shape.MyClass();
Vererbung von Klassenvar Person = WinJS.Class.define(function (firstname, lastname) { this._firstname = firstname; this._lastname = lastname;}, { fullname: { get: function () { return this.firstname + " " + this.lastname; } }});
var Employee = WinJS.Class.derive(Person, function(firstname, lastname, role) { this._firstname = firstname; this._lastname = lastname; this._role = role;}, { description : { get: function () { return this.fullname + " is a " + this._role; } }});
Data BindingTeil 7
Was ist an diesem Code schlecht?var button = document.getElementById('change-button'), person = document.getElementById('person');
button.addEventListener('clicked', function () { person.innerHTML = "Michael Müller";});
Schlecht testbar Abhängigkeit vom Code zur View Kann nicht wiederverwendet werden
<button id="change-button"></button><div id="person">Hans Muster</div>
Besserer Code
var viewModel = WinJS.Class.define(function () {}, { person = { name: "Hans Muster" }, changeName: function () { this.person.name = "Michael Müller"; }});
Gut testbar Keine Abhängigkeit zwischen Model und View Kann wiederverwendet werden
Binding fehlt
<button id="change-button"></button><div id="person">Hans Muster</div>
Data Binding in WinJS
Source TargetBindingConverter
var person = { name: "Hans Muster",};
<div id="root"> <p data-win-bind="textContent:name"></p></div>
var root = document.getElementById("root");WinJS.Binding.processAll(root, person);
DataContext
Bindable Wrappers
var person = { name: "Hans Muster",};
var bindablePerson = WinJS.Binding.as(person);
Erzeugt ein Wrapper mit Properties und Change-Notification.
var bindablePerson = WinJS.Class.define(function() { this._initObservable();}, { name: { get: function () { return getProperty("name"); }, set: function (value) { setProperty("name", value); } }}); WinJS.Class.mix(bindablePerson, WinJS.Binding.mixin);
Binding Mixinvar BindablePerson = WinJS.Class.define(function() { this._initObservable();}, { name : { get: function () { return getProperty("name"); }, set: function (value) { return setProperty("name", value); } }}); WinJS.Class.mix(WinJS.Binding.mixin, BindablePerson);
<div id="root"> <button data-win-bind="onclick:changeName"></button> <p data-win-bind="textContent:person.name"></p></div>
var ViewModel = WinJS.Class.define(function () {
},{ person: WinJS.Binding.as({ name: "Hans Muster" }), changeName: function () { this.person.name = "Michael Müller"; }});
Event Binding
WinJS.Binding.processAll(root, new ViewModel());
Errorperson is undefined.
ErrorValue is not supported within a declarative processing context.
Event Binding<div id="root"> <button data-win-bind="onclick:changeName"></button> <p data-win-bind="textContent:person.name"></p></div>
var ViewModel = WinJS.Class.define(function () { this.changeName = this._changeName.bind(this); this.changeName.supportedForProcessing = true;},{ person: WinJS.Binding.as({ name: "Hans Muster" }), _changeName: function () { this.person.name = "Michael Müller"; }});
WinJS.Binding.processAll(root, new ViewModel());
Löst Problem mit falschem this callback.Markiert die Funktion als “bindable”.
Binding Collections
var viewModel = WinJS.Class.define(function () { var persons = new WinJS.Binding.List();}, { add: function (name) { this.persons.push({ name: name }); }}); WinJS.Binding.processAll(root, viewModel);
<div data-win-control="WinJS.UI.ListView" data-win-bind="winControl.itemDataSource:persons:dataSource"></div>
Die Binding-List ruft beim Hinzufügen für jedes Item WinJs.Binding.as() auf.
Two Way Binding
<input type="text" data-win-bind="value:searchText Binding.Mode.twoway" />searchText: { get: function () { return this._searchText; }, set: function (value) { this._searchText = value;
this.doSearch(); } }
http://mvvmstack.codeplex.com/
Data TemplatesTeil 8
Data Templates
<div id="movie_template" data-win-control="WinJS.Binding.Template"> <div class="movie" data-win-bind="style.backgroundImage:posterUrl"> <div class="item-overlay"> <p data-win-bind="textContent:title"></p> </div> </div></div>
Tipp: Das äusserte <div> ist nicht Teil des Item-Templates.
<div id="moviesList" data-win-control="WinJS.UI.ListView" data-win-bind="winControl.itemDataSource:movies.dataSource;" data-win-options="{itemTemplate:select('#movie_template')}"></div>
Windows RuntimeTeil 9
Windows Runtime (WinRT)
Windows.Storage.KnownFolders.picturesLibrary .getFilesAsync().then(function (files) { files.forEach(function () { // Do something });});
WinRT (COM)
JavaScript Engine
Language Projection
Windows.DataWindows.DevicesWindows.GraphicsWindows.MediaWindows.NetworkingWindows.SecurityWindows.StorageWindows.Web
Zugriff auf Windows 8 Plattform Ressourcen
PromisesWinJS.xhr({ url: "http://www.google.com" }) .then(function (result) { out.innerText = "Success (" + result.responseText.length + " bytes)"; }, function (error) { out.innerHTML = "Failed to download: " + error.statusText; }, function (result) { out.innerText = "Downloading... " + result.readyState; });
Externe LibrariesTeil 10
jQuery
$('#rating').bind('change', function () { $('#message').append($('<p>Rated: ' + this.winControl.userRating + '</p>'));}); $('#appBarCommand').click(function () { $('#message').append($('<p>Clicked!</p>')); $('#rating')[0].winControl.userRating = 5;});
http://code.jquery.com/jquery-2.0.0b2.js
Rated: 3
Fazit
FazitHTML/JS sind bewährte, ausgereifte Technologien mit vielen Features. Damit lassen sich einfach, vollwertige Apps erstellen.
HTML/JS sind ideal, wenn man sich in einem Web-nahem Umfeld bewegt. (Rest-Services, JavaScript Libraries, bestehende Web-Lösungen)
Für komplexe Business-Logik würde ich immer noch C# bevorzugen (Typsicherheit, Refacoring, Namespaces/Classes/Interfaces Teil der Sprache)
WinJS ist stark bei Modern-UI-Controls, kommt aber in vieler Hinsicht (noch) nicht an Frameworks wie jQuery oder Knockout ran.
Viel Spass beim Ausprobieren und “en Guete”
© 2013 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a
commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.