<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Programmation Web Avancée vue-resource, vuex</title>
<meta name="cours-n" content="8">
<meta name="author" content="Rémi Emonet">
<meta name="venue" content="PWA M1 DSC">
<meta name="date" content="2017">
<meta name="affiliation" content="Université Jean Monnet − Laboratoire Hubert Curien">
<style type="text/css">
.slide.densish>ul {font-size: 70%;}
.commented-fs p {margin: 1em; }
.frflag {
background-image: url(media/frflag.svg);
width: 1em;
height: .75em;
display: inline-block;
background-size: contain;
}
</style>
<!--
<script src="deck.js/extensions/includedeck/load.js"></script>
<script src="extensions/slides-dev.js"></script>
-->
<script src="extensions/deck-packed.js"></script>
<script src="extensions/slides.js"></script>
<script>go()</script>
</head>
<body>
<div class="deck-container">
<div class="deck-loading-splash" style="background: black; color: chartreuse;"><span class="vcenter" style="font-size: 30px; font-family: Arial; ">Please wait, while our marmots are preparing the hot chocolate…</span></div>
<section class="smart">
# @chunk: chunks/title.md
# Questions ? <br/> Commentaires ? {no-print}
# @chunk: chunks/objectives.md
## Programmation Web Avancée <span>{var-cours-n}</span> : Plan {#plan overview}
- Questions Vue ? {rappelvue}
- Questions REST ? {rappelrest}
- Client REST JSON en Vue {restjs}
- Écosystème vue {vueeco}
# @copy:#plan
<!-- ################################### -->
# @copy:#plan: %+class:inred: .rappelvue
## Pourquoi Vue ? (dans ce cours) {libyli}
- Framework intéressant
- complet
- utilisé
- documentations dans plusieurs languages
- vs Angular
- 2 versions d'Angular
- Angular utilise typescript (proche de Spring etc)
- nous voulons apprendre/pratiquer javascript
- vs React.js
- react troublant avec : JSX, CSS, objet JS
- problème de licence dans React ?
- hum... <a href="https://code.facebook.com/posts/112130496157735/explaining-react-s-license/">août 2017</a> <a href="raw/cache-react-aout-2017.txt">_</a>
- ok (MIT) en <a href="https://github.com/facebook/react/commit/b765fb25ebc6e53bb8de2496d2828d9d01c2774b#diff-9879d6db96fd29134fc802214163b95a">septembre 2017</a>
# <a href="cours-07.html#slide-38" target="_blank">slides précédents</a> {no-print}
<!-- ################################### -->
# @copy:#plan: %+class:inred: .rappelrest
# <a href="cours-07.html#slide-88" target="_blank">slides précédents</a> {no-print}
<!-- ################################### -->
# @copy:#plan: %+class:inred: .restjs
# Accès à l'API github avec Vue
## Accès « REST » avec Vue et vue-resource {libyli}
- En *vue*, utilisation de `vue-resource`
- inclure `vue-resource.js` l'intègre automatiquement dans vue
- une fonction pour chaque *méthode*
- HTTP (GET⇒get(), DELETE⇒delete(), ..., POST⇒save())
- utilisation de « promesses » (*promises*)
- Mode 1: `this.$http`
```javascript
this.$http.get('https://......../1')
.then(response => {
// OK: get body data from response.body
}, response => {
// ERROR: ...
});
{slide dense}
```
- Mode 2: constructeur `this.$resource` (configurable)
```javascript
var r = this.$resource('http://........{/id}')
r.get({id: 1}).then(response => {
// OK: get body data
}, response => {
// ERROR: ...
});
{slide dense}
```
## Accès à l'API github avec Vue {libyli}
- API Github (v3)
- infos d'un utilisateur :
- `https://api.github.com/users/???????` {no}
- dépots d'un utilisateur :
- `https://api.github.com/users/???????/repos` {no}
- dépots en particulier :
- `https://api.github.com/repos/??USER??/??REPO??` {no}
- ...
- C'est parti ! {libyli}
- inclure vue et vue-resource
- récupérer les infos d'une repository
- afficher ces infos
- `name`, `description`, `owner` (`login`, `avatar_url`)
- un « cache » dans le « local storage »
- `JSON.parse(localStorage.getItem('....'))`
- `localStorage.setItem('....', JSON.stringify(...))`
## Accès à l'API github avec Vue (Suite) {libyli}
- C'est l'heure du picnic !
- Un composant `repo`
- Un composant `user` ?
- Plusieurs utilisateurs // USERS: "tifa90 SachaCo Tsompani BelaihouMohamed AbdelilahChet Kahi-Na MNour7 SouleymaneNianfo Touaibia khameds Raiden70 DavyUVD dimitribruyere Echyx ChrisJeamme"
- requêtes en parallèle
- `Promise.all(...)`
- Multicolonnes
- `columns: 4 ; column-rule: 1px solid black`
## Accès à notre server Spring {libyli}
- Rappel : hotels
- entité Hotel (name, nrooms), repository
- accessible en « REST » JSON sur `/api`, par ex, GET `/api/hotels`
```javascript
{
"_embedded": {
"hotels": [
{
"name": "ibis",
...
{slide denser}
```
- TODO : ajouter des données (sur `/data`)
- Un client en Vue (afficher la liste)
- NB: client sur une autre url : *Cross-origin resource sharing* (<a target="_blank" href="http://en.wikipedia.org/wiki/Cross-origin_resource_sharing">CORS</a>)
- CORS: 2 solutions, cf <a href="https://stackoverflow.com/questions/31724994/spring-data-rest-and-cors/42403956#42403956" target="_blank">stackoverflow</a>
- CORS: solution concise : ajouter `@CrossOrigin("*")` à la repo
- Ajout depuis Vue
- binding `newHotel: {name: "H", nrooms: 10}{}`
- POST ⇒ `.save(...)`
## Accès à notre server Spring (suite) {libyli}
- Ajout : ne pas devoir rafraichir
- ajout direct, validation/invalidation selon la requête
- astuces JS + Vue (changer et **rafraichir**)
```javascript
# js : copier un objet et changer/ajouter des propriétées
var nouv = {...existant, nouvprop: 'bidule'};
# modifier un élément d une liste
nouv.truc = "machin"
this.hotels = [...this.hotels]
# ajouter dans une liste
this.hotels = [...this.hotels, nouv]
# enlever d une liste
this.hotels = this.hotels.filter(h => h!==nouv)
# remplacer dans une liste
this.hotels = this.hotels.map(h => h!==nouv ? h : nouvnouv)
{slide dense}
```
- Supprimer un hotel
- HATEOAS : `...$http.delete(h._links.self.href)`
<!-- ################################### -->
# @copy:#plan: %+class:inred: .vueeco
## Aller plus loin avec Vue {libyli}
- Vue cli (command line interface)
- <a href="https://vuejs.org/v2/guide/installation.html#CLI" target="_blank">https://vuejs.org/v2/guide/installation.html#CLI</a>
- pour générer des projets à partir de templates
- et outils js « usine à gaz » (webpack, babel, ...)
- Vue router
- <a href="https://router.vuejs.org/en/" target="_blank">https://router.vuejs.org/en/</a>
- <a href="https://router.vuejs.org/fr/" target="_blank">https://router.vuejs.org/fr/</a> <span class="frflag"/>
- Vuex
- <a href="https://vuex.vuejs.org/en/" target="_blank">https://vuex.vuejs.org/en/</a>
- <a href="https://vuex.vuejs.org/fr/" target="_blank">https://vuex.vuejs.org/fr/</a> <span class="frflag"/>
- Applications natives avec Vue.js ?
- Weex <a href="https://weex.incubator.apache.org/">https://weex.incubator.apache.org/</a>
- Nativescript+Vue <a href="https://nativescript-vue.org/">https://nativescript-vue.org/</a>
</section>
<!-- deck.status snippet -->
<p class="deck-status deck-progress-10"> <span class="deck-status-current"></span> / <span class="deck-status-total"></span> − <span class="var-author">will be replaced by the author</span> − <span class="var-title">will be replaced by the title</span></p>
<a data-progress-size=": spe.top(15, 555); height: 45*designRatio; left: slide.right - 90*designRatio; width: 90*designRatio" class="ccby" href="http://en.wikipedia.org/wiki/Creative_Commons_license" title="This work is under CC-BY licence." target="_blank"></a>
<a class="ujm" data-progress-size=": spe.top(15, 525); height: 65*designRatio; left: slide.left; width: 130*designRatio" target="_blank"></a>
</div>
<!-- clicky Cla -->
<script type="text/javascript">
var clicky_site_ids = clicky_site_ids || [];
clicky_site_ids.push(100779706);
(function() {
var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = '//static.getclicky.com/js';
( document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0] ).appendChild( s );
})();
</script>
<noscript><p><img alt="Clicky" width="1" height="1" src="//in.getclicky.com/100779706ns.gif" /></p></noscript>
<!-- Histats.com START (aync)-->
<script type="text/javascript">var _Hasync= _Hasync|| [];
_Hasync.push(['Histats.start', '1,2767123,4,0,0,0,00010000']);
_Hasync.push(['Histats.fasi', '1']);
_Hasync.push(['Histats.track_hits', '']);
(function() {
var hs = document.createElement('script'); hs.type = 'text/javascript'; hs.async = true;
hs.src = ('http://s10.histats.com/js15_as.js');
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(hs);
})();</script>
<noscript><a href="http://www.histats.com" target="_blank"><img src="http://sstatic1.histats.com/0.gif?2767123&101" alt="javascript hit counter" border="0"></a></noscript>
<!-- Histats.com END -->
</body>
</html>