Your SlideShare is downloading. ×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Entwurfsmuster für mobile JavaScript-Web-Apps - WebTechConference 2012

1,585
views

Published on

http://www.opitz-consulting.com/go/3-4-898 …

http://www.opitz-consulting.com/go/3-4-898

JavaScript-Anwendungen werden immer leistungsfähiger, aber auch immer komplexer. Wie kann eine Anwendung trotz wachsender Größe wartbar und testbar bleiben? Entwurfsmuster wie Data Binding, Dependency Injection und Modularisierung helfen, dieses Ziel zu erreichen.

Tobias Bosch erläuterte in seinem Vortrag bei der WebTechConference am 17.10.2012 in Mainz die Konzepte und verdeutlicht sie an einem Beispiel mit AngularJS und jQuery Mobile.

--
Zukunft?! Wir arbeiten dran.
Mobile Solutions by OPITZ CONSULTING
http://www.opitz-consulting.com/go/3-4-898

Über uns:

Als führender Projektspezialist für ganzheitliche IT-Lösungen tragen wir zur Wertsteigerung der Organisationen unserer Kunden bei und bringen IT und Business in Einklang. Mit OPITZ CONSULTING als zuverlässigem Partner können sich unsere Kunden auf ihr Kerngeschäft konzentrieren und ihre Wettbewerbsvorteile nachhaltig absichern und ausbauen.

Über unsere IT-Beratung: http://www.opitz-consulting.com/go/3-8-10
Unser Leistungsangebot: http://www.opitz-consulting.com/go/3-8-874
Karriere bei OPITZ CONSULTING: http://www.opitz-consulting.com/go/3-8-5

Published in: Technology

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,585
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
0
Comments
0
Likes
2
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Entwurfsmuster fürmobile JavaScript-Web-AppsTobias BoschOPITZ CONSULTING Deutschland GmbH
  • 2. Wer bin ich?tobias.bosch@opitz-consulting.com (@tigbro)
  • 3. Mission MärkteWir entwickeln gemeinsam mit allen  BranchenübergreifendBranchen Lösungen, die dazu führen, dass  Über 600 Kundensich diese Organisationen besser entwickeln 29%als ihr Wettbewerb. 29% Handel / Logistik / Dienstleistungen Industrie / Versorger /Unsere Dienstleistung erfolgt Telekommunikationpartnerschaftlich und ist auf eine langjährige 42%Zusammenarbeit angelegt. Öffentliche Auftraggeber / Banken und Versicherungen / Vereine und VerbändeLeistungsangebot Eckdaten Business IT Alignment  Gründung 1990 Business Information Management  400 Mitarbeiter Business Process Management  8 Standorte Anwendungsentwicklung SOA und System-Integration IT-Infrastruktur-Management © OPITZ CONSULTING GmbH 2012 Seite 3
  • 4. Wer sind Sie?
  • 5. In diesem Vortrag geht‘s um ... ... die Entwicklung testbarer und wartbarermobiler JavaScript Web-Apps
  • 6. In diesem Vortrag geht‘s um ... ... die Entwicklung testbarer und wartbarermobiler JavaScript Web-Apps
  • 7. In diesem Vortrag geht‘s um ... ... die Entwicklung testbarer und wartbarermobiler JavaScript Web-Apps
  • 8. Die Beispiel-App ...http://tigbro.github.com/todo-mobilehttps://github.com/tigbro/todo-mobile
  • 9. Architektur
  • 10. "Multi Page Web App"Browser Server HTML-Page Model View Data Backend UI Values Controller
  • 11. "AJAX Web App"Browser Server Change ModelAJAX- View Ba DataEngine Controller Events
  • 12. "Single Page Web App" Browser Server Model View Data Backend Controller
  • 13. Komponenten-Bibliotheken
  • 14. jQuery Mobile http://jquerymobile.com/
  • 15. Die Beispiel-App
  • 16. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div></div> jQuery Mobile Markup
  • 17. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div></div> jQuery Mobile Markup
  • 18. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div></div> jQuery Mobile Markup
  • 19. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div></div> jQuery Mobile Markup
  • 20. <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div></div> jQuery Mobile Markup
  • 21. DOM-Transformationdurch jQuery-Mobile
  • 22. <input type="checkbox" id="todo1"/><label for="todo1">create a mobile todo app</label><div class="ui-checkbox"> <input type="checkbox" name="todo.done" id="todo1"> <label class="ui-btn ui-btn-up-c ui-btn-icon-left ui-btn-corner-all ui-checkbox-off" for="todo1" data-theme="c"> <span class="ui-btn-inner ui-btn-corner-all"> <span class="ui-btn-text">create a mobile todo app</span> <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow"></span> </span> </label></div> jQuery Mobile Markup Transformation
  • 23. <input type="checkbox" id="todo1"/><label for="todo1">create a mobile todo app</label><div class="ui-checkbox"> <input type="checkbox" name="todo.done" id="todo1"> <label class="ui-btn ui-btn-up-c ui-btn-icon-left ui-btn-corner-all ui-checkbox-off" for="todo1" data-theme="c"> <span class="ui-btn-inner ui-btn-corner-all"> <span class="ui-btn-text">create a mobile todo app</span> <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow"></span> </span> </label></div> jQuery Mobile Markup Transformation
  • 24. Two Way Data Binding
  • 25. Manuelles Binding
  • 26. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  • 27. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  • 28. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  • 29. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  • 30. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  • 31. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  • 32. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  • 33. $(#addTodo).submit(function(event) { addTodo(); event.preventDefault();});function addTodo() { var inputText = $(#inputText).val(); var list = $(#todos); var entryCount = list.find(input).length; list.append(entryTemplate(entryCount, inputText)); list.trigger(create); $(#inputText).val();}function entryTemplate(index, name) { var id = todo + index; return <input type="checkbox" id=" + id + "/> + <label for=" + id + "> + name + </label>;}
  • 34. Das Ziel sollte aber sein: function TodoController() { this.todos = []; this.inputText = ; this.addTodo = function() { this.todos.push({ name: this.inputText, done: false }); this.inputText = ; }; }
  • 35. Angular JSDeclarative MVC withUI Templates Dependency InjectionTwo-Way FrameworkData Binding http://angularjs.org/#/
  • 36. Two-Way Databinding read read write Data- writeDOM Controller binding watch watch
  • 37. Scopes Scope Expressions $get(<expr>) inputText todos.length $set(<expr>, <value>) ...$watch(<expr>, <callback>)
  • 38. Demo
  • 39. Das Ziel ...function TodoController() { this.todos = []; this.inputText = ; this.addTodo = function() { this.todos.push({ name: this.inputText, done: false }); this.inputText = ; };}
  • 40. Mit Angular ...function TodoController($scope) { $scope.todos = []; $scope.inputText = ; $scope.addTodo = function() { $scope.todos.push({ name: $scope.inputText, done: false }); $scope.inputText = ; };}TodoController.$inject = [$scope];
  • 41. <div data-role="page" TodoController-Scope ng-controller="TodoController"> inputText: new todo erzeugt <input type="text" todos: [...] bindet ng-model="inputText" bindet <div ng-repeat="todo in todos"> erzeugt Repeater Scope Repeater Scope Repeater Scope todo: { todo: todo: { { <input type="checkbox" ng-model="todo.done"/> done: false done: false done: false bindet name: makemoney name: makemoney name: makemoney <label> {{todo.name}} } </label> bindet }}
  • 42. jQuery Mobile und AngularJS Das Problem: Die DOM-Manipulationen von jQuery Mobile und AngularJS müssen koordiniert werden!
  • 43. jQuery Mobile und AngularJS Die Lösung:jQuery Mobile Angular Adapter
  • 44. jQuery Mobile Angular AdapterKoordination von jQuery Mobile und AngularJS Erweiterungen für mobile Web-Apps Open Source unter https://github.com/tigbro/ jquery-mobile-angular-adapter
  • 45. Dependency Injection
  • 46. Dependency Injection ist ein Entwurfsmuster und dient dazu, die Abhängigkeiten zwischen Komponenten zu minimieren. Es überträgt die Verantwortung für dasErzeugen und die Verknüpfung von Objekten an ein extern konfigurierbares Framework http://de.wikipedia.org/wiki/Dependency_Injection
  • 47. Dependency Injection ist ein Entwurfsmuster und dient dazu, die Abhängigkeiten zwischen Komponenten zu minimieren. Es überträgt die Verantwortung für dasErzeugen und die Verknüpfung von Objekten an ein extern konfigurierbares Framework http://de.wikipedia.org/wiki/Dependency_Injection
  • 48. Beispiel: Backend-Anbindung function refreshTodos() { var self = this; read(ToDoApp, function(response) { self.todos = response; }); }
  • 49. Beispiel: Backend-Anbindung function refreshTodos() { var self = this; read(ToDoApp, function(response) { self.todos = response; }); }
  • 50. Beispiel: Backend-Anbindung var readUrl = https://secure.openkeyval.org/; function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); }
  • 51. Beispiel: Backend-Anbindung var readUrl = https://secure.openkeyval.org/; function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); }
  • 52. Beispiel: Backend-Anbindung var readUrl = https://secure.openkeyval.org/; function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); }
  • 53. Beispiel: Backend-Anbindung waitDialogtodoController todoStore key valuekey value key value ... ...refreshTodos ... read ...todoStore waitDialog jsonp jsonp key value ... ... created by Factories
  • 54. Beispiel: Backend-Anbindung waitDialogtodoController todoStore key valuekey value key value ... ...refreshTodos ... read ...todoStore waitDialog jsonp jsonp key value ... ... created by Dependency Injection
  • 55. Angular JSDeclarative MVC withUI Templates Dependency InjectionTwo-Way FrameworkData Binding http://angularjs.org/#/
  • 56. Services und DI mit Angularfunction jsonpFactory() { // returns jsonp function // ...}function waitdialogFactory() { // returns waitdialog object // ...}
  • 57. Services und DI mit Angularvar module = angular.module("todo", []);
  • 58. Services und DI mit Angularvar module = angular.module("todo", []);module.factory(jsonp, jsonpFactory);module.factory(waitdialog, waitdialogFactory);
  • 59. Services und DI mit Angularvar module = angular.module("todo", []);module.factory(jsonp, jsonpFactory);module.factory(waitdialog, waitdialogFactory);function todoStoreFactory(jsonp, waitdialog) { function read(key, success) { // use jsonp, waitdialog here } return { read: read };}
  • 60. Services und DI mit Angularvar module = angular.module("todo", []);module.factory(jsonp, jsonpFactory);module.factory(waitdialog, waitdialogFactory);function todoStoreFactory(jsonp, waitdialog) { function read(key, success) { // use jsonp, waitdialog here } return { read: read };}todoStoreFactory.$inject = [jsonp, waitdialog];
  • 61. Services und DI mit Angularvar module = angular.module("todo", []);module.factory(jsonp, jsonpFactory);module.factory(waitdialog, waitdialogFactory);function todoStoreFactory(jsonp, waitdialog) { // ...}todoStoreFactory.$inject = [jsonp, waitdialog];module.factory(todoStore, todoStoreFactory);
  • 62. Controller und DI mit Angularfunction TodoController($scope, todoStore) { ...}TodoController.$inject = [$scope, todoStore];module.controller("rylc.TodoController", TodoController);
  • 63. Controller und DI mit Angularfunction TodoController($scope, todoStore) { ...}TodoController.$inject = [$scope, todoStore];module.controller("rylc.TodoController", TodoController);
  • 64. Controller und DI mit Angularfunction TodoController($scope, todoStore) { ...}TodoController.$inject = [$scope, todoStore];module.controller("rylc.TodoController", TodoController);
  • 65. jQuery Mobile Angular AdapterKoordination von jQuery Mobile und AngularJS Erweiterungen für mobile Web-Apps Open Source unter https://github.com/tigbro/ jquery-mobile-angular-adapter
  • 66. jQuery Mobile Angular Adapter Mobile Events
  • 67. <div id="welcomePage" data-role="page" ngm-pagebeforeshow="rental.prefetchMasterData()" ngm-pagebeforehide="rental.clearMessages()"> ...</div>
  • 68. <div id="welcomePage" data-role="page" ngm-pagebeforeshow="rental.prefetchMasterData()" ngm-pagebeforehide="rental.clearMessages()"> ...</div> Unterstütze Events: vclick swipe pagebeforeshow swiperight pageshow swipeleft pagebeforehide tap pagehide taphold
  • 69. jQuery Mobile Angular Adapter Shared Controller
  • 70. LoginPage<div id="loginPage" Scope ng-controller="LoginController"> login <a ngm-click="login()">
  • 71. LoginPage<div id="loginPage" Scope ng-controller="LoginController"> login <a ngm-click="login()"><div id="welcomePage" WelcomePage ng-controller="WelcomeController"> Scope logout <a ngm-click="logout()">
  • 72. LoginPage<div id="loginPage" Scope ngm-shared-controller= Authentication- "auth:AuthenticationController"> auth Controller Scope <a ngm-click="login()"> login logout<div id="welcomePage" WelcomePage ngm-shared-controller= Scope "auth:AuthenticationController"> auth <a ngm-click="logout()">
  • 73. LoginPage<div id="loginPage" Scope ngm-shared-controller= Authentication- "auth:AuthenticationController"> auth Controller Scope <a ngm-click="auth.login()"> login logout<div id="welcomePage" WelcomePage ngm-shared-controller= Scope "auth:AuthenticationController"> auth <a ngm-click="auth.logout()">
  • 74. LoginPage<div id="loginPage" Scope ngm-shared-controller= Authentication- "auth:AuthenticationController"> auth Controller Scope <a ngm-click="auth.login()"> login logout<div id="welcomePage" WelcomePage ngm-shared-controller= Scope "auth:AuthenticationController, "rental:RentalController"> auth <a ngm-click="auth.logout()"> rental <a ngm-click="rental.initRental()"> Rental- Controller Scope initRental searchCar
  • 75. LoginPage<div id="loginPage" Scope ngm-shared-controller= Authentication- "auth:AuthenticationController"> auth Controller Scope <a ngm-click="auth.login()"> login logout<div id="welcomePage" WelcomePage ngm-shared-controller= Scope "auth:AuthenticationController, "rental:RentalController"> auth <a ngm-click="auth.logout()"> rental <a ngm-click="rental.initRental()"> Rental-<div id="rentalPage" Controller Scope ngm-shared-controller= RentalPage "auth:AuthenticationController, Scope initRental "rental:RentalController"> searchCar auth <a ngm-click="rental.searchCars()"> rental
  • 76. jQuery Mobile Angular Adapter Wait Dialog
  • 77. waitDialog.show(loading);waitDialog.hide();waitDialog.show(click to abort, onClickCallback);
  • 78. jQuery Mobile Angular Adapter Paging / Load More
  • 79. <fieldset ng-repeat="todo in todos | paged:pager:5"> <input type="checkbox" ng-model="todo.done" id="checked"> <label for="checked">{{todo.name}}</label></fieldset><div ngm-if="pager.hasMore"> <a href="#" ngm-click="pager.loadMore()" data-role="button"> Load more </a></div>
  • 80. <fieldset ng-repeat="todo in todos | paged:pager:5"> <input type="checkbox" ng-model="todo.done" id="checked"> <label for="checked">{{todo.name}}</label></fieldset><div ngm-if="pager.hasMore"> <a href="#" ngm-click="pager.loadMore()" data-role="button"> Load more </a></div>
  • 81. Fazit Auch bei der Entwicklung von JavaScript Clientssollten geeignete Entwurfsmuster angewendet werden!
  • 82. FazitBibliotheken und Frameworks helfen bei der Umsetzung!
  • 83. FazitEine praxiserprobte Kombination für die Entwicklung mobiler Web-Apps: jQuery Mobile + AngularJS + Adapter
  • 84. In the hive 11: nectar and pollen by Max xx, http://www.flickr.com/photos/max_westby/4567762490 BooksBy Rodrigo Galindez, http://www.flickr.com/photos/rodrigogalindez/4637637337/ IMG_1300-Edit by Susan E Adams, http://www.flickr.com/photos/susanad813/3912914836/ Doble Via by amslerPIX, http://www.flickr.com/photos/amslerpix/6242266697/ MacBook Pro Keyboardby superstrikertwo, http://www.flickr.com/photos/superstrikertwo/4989727256/ Stubborn Last Drop by RogueSun Media, http://www.flickr.com/photos/shuttercat7/627798443/
  • 85. Vielen Dankfür Ihr Interesse! @tigbro
  • 86. www.opitz-consulting.com/go_mobile

×