Please wait, while our marmots are preparing the hot chocolate…
# @chunk: chunks/title.md
# Questions ?
Commentaires ? {no-print}
# @chunk: chunks/objectives.md
## Programmation Web Avancée {var-cours-n} : Plan {#plan overview}
- Javascript {rappeljs}
- Vue : les bases {vue}
- Vue : composants {vuecomp}
- Principes REST {rest}
- Serveur REST en Spring {springrest}
- Client REST JSON en Vue {restjs}
# @copy:#plan
# @copy:#plan: %+class:inred: .rappeljs
# slides précédents
## Fonctions JS {libyli}
- Fonction nommée « classique » en JavaScript
```javascript
function toto(a,b) {
return a+b;
}
alert(toto(1,3));
{dense slide}
```
- Fonction JavaScript : objet de première classe
```javascript
var f = function(a) {
return a*a;
}
alert(f(2));
var squares = [1,2,3].map(f);
{dense slide firstorder}
```
- @anim: .firstorder>span:nth-of-type(4) | .firstorder>span:nth-of-type(5)
- Fonction anonyme
```javascript
var squares = [1,2,3].map(function(a) {
return a*a;
});
setTimeout(function() { alert("Hello"); },
3000);
{dense slide anonymous}
```
- @anim: .anonymous>span:nth-of-type(5), .anonymous>span:nth-of-type(6)
## Objets et Classes JS {libyli}
- JS n'est pas un langage orienté classe (Java)
- JS est un langage à prototype
- Très dynamique
- Attention à `this` (≠ Java)
- un objet « contexte »
- pas nécessairement d'un type donné (comme la classe)
- Plus flexible que les langages à classes
- Le mot clé `class` arrive en ES6 ;-(
## ES6 (ES2015) {libyli}
- Syntaxe : class
- `constructor()`, `super()`
- `get`, `set`
- Syntaxes
- Modifieurs et portées de variables : const, var, val, let
- *Arrow Functions* et gestion du `this`
- Interpolation de string `̀ Hello ${name}̀ ` (backticks)
- Propriétés : raccourcis, méthodes, prop. construire (`[ «» ] : «»`)
- Construction et déconstruction pour listes et objets (avec valeur par défaut et y compris en param)
- *Rest* et *Spread* avec `...` (y compris en paramètre, syntactic sugar pour `arguments`)
- Paramètres par défaut `a=2`
- Autres : modules, generator
- etc.
## Gestion du `this` et *Arrow Functions* (ES6) {libyli}
- Attention à `this` (≠ Java)
- un objet « contexte » variable
- pas nécessairement d'un type donné (comme la classe)
```javascript
var o = {
i: 10000,
test: function() {
this.incr = function() {
this.i += 1;
console.log(this.i);
};
this.incr2 = () => {
this.i += 1;
console.log(this.i);
};
this.incr();
this.incr2();
setTimeout(this.incr, 300); // executer 300 ms plus tard
// TODO: .bind(this)
setTimeout(this.incr2, 600); // executer 600 ms plus tard
},
};
o.test();
{slide dense}
```
# @copy:#plan: %+class:inred: .vue
# Sans et avec Vue :
des champs synchronisés
## Ce qu'on a utilisé
- Javascript
- `Array.from()`, `document.querySelectorAll`, `.forEach`
- `Math.random()`
- `.oninput`, `.tagName`, `.value`, `.textContent`
- CSS (`background`, `border`, `padding`)
## Vue / Vuex
- Vue
- framework léger pour applications interactives coté client
- similarité avec Angular, React, Ember, ...
- approche composant avec bindings
- https://vuejs.org/v2/guide/
- https://fr.vuejs.org/v2/guide/index.html
- Vuex
- https://vuex.vuejs.org/en/
- https://vuex.vuejs.org/fr/
# Sans et avec Vue :
des champs synchronisés
## Vue : Principes {libyli}
- Données observables, rendu automatiquement à jour
- Template HTML+CSS
- avec des moustaches `{{ ... }}{}` (n'importe quelle expression ecmascript)
- avec des directives *vue*, éléments avec des attributs `v-...`
- accès automatique au *ViewModel*
- Objet javascript de type `Vue`
```javascript
var vm = new Vue({
el: ..., // selecteur CSS de l'élément à traiter
data: { // objet contenant l'état / les données / le ViewModel
...
},
methods: { // les actions / le comportement
...
},
computed: { // des fonctions, chacune renvoie une propriété calculée
... // possibilité de {get: ..., set: ...} pour un mutateur calculé
},
watch: { // listener quand une des propriétés de data change
...
}
});
{slide dense}
```
## Vue : Liaison unidirectionnelle {libyli}
- Comme les moustaches mais pour des attributs
- Utlisation de `v-bind:...` ou `:...`
- Cas des attributs booléen (présent ou non dans le DOM), e.g. `:disabled="ind==0"`
## Vue : Liaison avec des formulaires {libyli}
- Pour les éléments éditables (input, select ou textarea)
- Liaison bidirectionnelle (de la propriété `value` de ces éléments)
- Attribut `v-model="..."`
- Valeur : nom de la propriété de l'état
- Modificateurs en suffixe `.lazy`, `.number`, `.trim`
## Vue : Gestion des événements {libyli}
- Événements avec attributs `v-on:...` (ou `@...`)
- Valeur de l'attribut
- nom de la méthode
- ou, code à exécuter
- Modificateurs en suffixe
- gestion de l'événement : `.stop`, `.prevent`, `.once`, ...
- pour les touches et/ou click souris : `.shift`, `.ctrl`, `.exact`, ...,
- pour spécifier une touche : `.enter`, `.up`, `.space`, `.65`, ...,
- pour spécifier un bouton de la souris : `.left`, `.middle`, `.right`
```
click ou ctrl+mouvement
click ou ctrl+mouvement
{slide denser}
```
## Vue : conditions et itérations {libyli}
- Affichage conditionnel avec `v-if="..."`
- expression booléene décidant du rendu ou non de l'élément
- NB: l'élément n'est alors pas dans le DOM
- Affichage en boucle (comme Thymeleaf) avec `v-for="vvv in lll"`
- nom de variable arbitraire
- possibilité d'avoir auss l'indice avec `(vvv, iii) in lll`
## Vue : Autre
- Variables de contexte selon les cas: `$index` (boucles), `$event` (listener), ...
# @copy:#plan: %+class:inred: .vuecomp
## Vue : Composants {libyli}
- But
- encapsuler un rendu et/ou comportement
- créer ses propres éléments, par ex, `〈pwa year="2017"〉Rocks〈/pwa〉{dense}`
- Fonction `Vue.component`
- `props`: liste des attributs attendus
- `template`: template HTML
- attention, `data` doit être une fonction (si présent)
```
Vue.component('nom-du-tag', {
props: ['msg'],
template: '{{ msg }}
',
data: function () {
return {
...
}
},
});
{slide}
```
- Utilisation
```
{slide}
```
## Vue : Émettre des événements depuis un composant {libyli}
- Dans le composant
- utilisation de la fonction `$emit`
- par ex : `$emit('truc')`
- Dans le parent, ecoute classique
- par ex : `v-on:truc` ou `@truc`
- Possibilité d'utiliser `v-model` (bidirectionnel)
- avoir une prop `value`
- émettre des événements `input` (`this.$emit('input', v)`)
## Vue : à voir
- composants dans un fichier `.vue` (pas de `template:'....'`)
- transition / animations
- packaging
- vue cli : ligne de commande
- vuex : gestion d'état centralisé
- routeur : url, bookmarking, deep linking
- directives perso
# @copy:#plan: %+class:inred: .rest
# Principes REST : *Representational State Transfer*
## *Representational State Transfer* {libyli}
- Thèse de Roy T. Fielding (et [fr])
- Un style d'architecture
- un ensemble de ressources
- des liens entre ces ressources
- comme une bonne application Web
- Hypermedia as the engine of application state (HATEOAS) {slide} // important : le client choisi ce qu'il fait, le serveur guide
- Propriété et objectifs
- performance et passage à l'échelle // cacheable
- simplicité et évolutivité
- Principes {libyli}
- client-serveur, *stateless* (sans état), couches (cache, sécurité, ...) // ne sait pas si on parle au serveur directement
- ressources auto-décrites avec identifiant et métadonnées, HATEOAS
- Résumé en Français
## *RESTful HTTP APIs* : REST sur HTTP {libyli} // RESTful (adjectif de REST)
- Ressource : identifiant et représentation
- URI (*Unique Resource Identifier*), `https://github.com/apache/spark {dense}`
- métadonnées, ex : `Content-Type: text/html{dense}`, `Content-Encoding: gzip{dense}`
- données, ex : HTML gzippé
- {no}
- NB : pas de verbes ou actions dans les URI // capital !
- ok : `https://github.com/repositories`
- ko : `https://github.com/createNewRepo?name=pwa`
- Protocole *stateless* : HTTP avec méthodes HTTP {libyli}
- GET : sûre (sans effets de bords)
- récupère la représentation d'une ressource
- liste le contenu d'une collection
- DELETE : idempotente (même résultat si appliqué plusieurs fois)
- supprime une ressource existante
- supprime une collection
- PUT : idempotente
- remplace ou met à jour une ressource
- remplace ou met à jour une collection
- POST :
- crée une nouvelle entrée dans une collection
# @copy:#plan: %+class:inred: .springrest
# (Tutoriel Spring+REST+React)
## Création d'un Modèle REST en Spring {libyli}
- {no}
- But : partager un modèle JPA en REST, au format JSON
- Étapes
- modèle : entités JPA
- service : repository `JpaRepository` (ou `CrudRepository`)
- `spring-data-rest-webmvc` (dépendance maven)
- ou à la main avec `@RestController`, `@Valid`, `RequestMethod.*`
- (configuration : `spring.data.rest.base-path=/api`)
- si client est à une autre url : *Cross-origin resource sharing* (CORS)
- Test simplifiés
```
curl -X GET http://localhost:8080/api/hotels
curl -X POST http://localhost:8080/api/hotels -H "Content-Type: application/json" -d '{"name":"ibis", "nrooms":444}'
curl -X GET http://localhost:8080/api/hotels
curl -X GET http://localhost:8080/api/hotels/ibis
curl -X DELETE http://localhost:8080/api/hotels/ibis
curl -X GET http://localhost:8080/api/hotels
{denser slide}
```
- {no}
- Let's do it ! (hotels)
- (plugin JSONView + cfg content `application/hal+json`)
# @copy:#plan: %+class:inred: .restjs
# à venir
/ − will be replaced by the author − will be replaced by the title