![]() |
![]() |
Accueil > Intranet Michel Buffa > Master 2 INTENSE: Frameworks JavaScript et Server-Side JavaScript BD NoSQL Cloud etc.
Master 2 INTENSE: Frameworks JavaScript et Server-Side JavaScript BD NoSQL Cloud etc.De $1Table des matières
IntroductionDans ce cours nous allons voir plusieurs aspects du développement Web Moderne :
A faire : si vous êtes sous windows, installer un bon terminal en ligne de commande comme http://cmder.net/ ou autre (github bash, etc.) si je vous vois avec une fenêtre DOS basique vous allez m'entendre ! Séance 1 : état des lieux du développement Web, intro à VueJS
DOM or not to DOM ?Ecriture en live coding d'un gestionnaire de todos :Nous allons comparer plusieurs versions:
A propos de REST:
Remarque : on peu faire des requêtes REST avec XhR2, fetch API(pour les curieux : quelques mots sur GraphQLet Appolo) On peut aujourd'hui gérer la progression des uploads et downloads avec fetch et l'API des streams (voir https://streams.spec.whatwg.org/demos/) Suite de l'étude de VueJSCréer des composants avec VueJS Reprenez un des derniers exemples faits avec VueJS, ma gestion d'une todo list: http://jsbin.com/pigolozuva/1/edit?h...console,output Dans cet exemple, on ne peut pas instancier plusieurs "Vues". Mais on peut associer la VueJS à un "faux" élement custom HTML, comme ici: http://jsbin.com/penadanife/edit?htm...console,output Exercice à faire: inspirez-vous de cet exemple pour gérer une liste de hobbies, mais avec les contraintes indiquées dans les commentaires HTML de ce squelette d'application: http://jsbin.com/guwetoy/edit?html,js,output Correction (ne regarder qu'après avoir vraiment essayé, ou vu la correction en live conding) : http://jsbin.com/guwetoy/1/edit Développer en mode "CLI" avec un environnement de build/testy
Cette fois-ci, pour terminer l'introduction à VueJS, le plus élégant/simple des trois gros frameworks "industriels" modernes (React, VueJS, Angular), nous allons regarder comment on peut développer avec "un environnement de développement", qu'on appelle "CLI" pour "Command Line Environment". Les trois frameworks cités, mais aussi Polymer dont on vient de parler, proposent un environnement "CLI". Travail à faire :
<template> <div id="app"> Hello {{msg}} <div> <router-link to="/">Home</router-link> <router-link to="/blog">Blog</router-link> <router-link to="/compte">compte</router-link> </div> <router-view></router-view> <app-user></app-user> <p>Ceci est un test</p> </div> </template> Correction de l'exercice: VueJSExoCli.zip, faire "npm install" et "npm run dev" une fois dezippé. Séance 2: suite VueJS, intro à ReactAvoir une vue de l'écosystème JavaScript (sites vus en cours)
Comment faire de belles interfaces Web avec VueJS ?Element et iView sont les deux kits de composants d'interface utilisateur les plus populaires, tous deux axés sur le développement rapide d'interfaces utilisateur Desktop. Mint UI et vux, d'autre part, sont les deux packages les plus populaires pour faire des interfaces utilisateur pour mobile. Vuetify est un framework de composants au look and feel "Material Design" qui peut être utilisé à la fois pour les applications web mobiles et de bureau, et est probablement le plus riche en fonctionnalités de rendu côté serveur, support des Progressive Web Apps et templates en mode CLI. Il y a aussi Vue Material qui met davantage l'accent sur le strict respect des spécifications Material Design. ALLEZ, PASSEZ UN PETIT MOMENT 0 EXPLORER CES PACKAGES DE GUI POUR VueJS !!! Exercice à faire pour la semaine prochaine : proposer une démo dans un exemple fait par vous, utilisant des composants de un ou plusieurs d'entre eux. Introduction à ReactExercices d'introduction, dans une IDE en ligneOn peut faire du react dans JsBin/JsFiddle/CodePen, mais croyez-moi, juste pour de petits exemples !
Exercice à faire en vous aidant des exercices précédents:Pour vous donner une idée du résultat attendu,voici l'équivalent en VueJS: http://jsbin.com/guwetoy/1/edit?html,output Je conseille de partir de cet exemple React: le composant en classe ES6 En vous aidant de l'exemple fait en classe en live coding, voud devrez faire incrémentalement, en testant après chaque étape :
ICI UNE CORRECTION: https://codepen.io/w3devcampus/pen/b...m?editors=1010 Exercices avec un environnement "CLI"Si on va voir la page de facebook sur "how to start with React", il y a un chapitre qui concerne le mode "CLI": https://reactjs.org/docs/add-react-to-a-new-app.html
Exercice: refaire dans le projet les hobbies en mode CLI !
Séance 3: Utilisation de FireBase, une base de données basée cloud synchronisée
ETAPE 1 : Il faut commencer par modifier l'exemple des hobbies pour qu'il fonctionne non pas avec un tableau mais avec un objet. Firebase ne sais synchroniser que des objets, pas des tableaux: Dans App.js : this.state = { hobbies : { hobby0: 'tennis', hobby1: 'golf' } // ... }; Il faudra modifier plusieurs parties du code en conséquence...
Ex de code: addHobby() {
/* OLD VERSION WITH ARRAY
const oldHobbies = this.state.hobbies;
this.setState({
hobbies: oldHobbies.concat(this.state.input),
input : ""
});
*/
// faire une copie de l'objet hobbies
const hobbies = {...this.state.hobbies};
// Ajouter le nouveau hobby
const timestamp = Date.now();
hobbies[`hobby-${timestamp}`] = this.input.value;
this.setState({hobbies});
console.log(this.state.hobbies)
}
removeHobby(key) {
/* OLD VERSION WITH ARRAYS
const oldHobbies = this.state.hobbies;
const position = oldHobbies.indexOf(hobby);
this.setState({
hobbies: oldHobbies.filter((el, index) => {
return (index !== position)
}),
hobbyWasDeleted : true
});
*/
// faire une copie de l'objet hobbies
const hobbies = {...this.state.hobbies};
// Supprime le hobby dont la cle key a ete passee en parametres
//delete hobbies[key]; // ne marche pas avec firebase
hobbies[key] = null;
// Mettre a jour l'etat
// En ES6 vous pouvez juste taper {'hobbies'} au lieu de {hobbies:hobbies}
this.setState({hobbies});
}
Et pour render, exemple d'iterateur sur un objet, comparer par rapport au code qui itere sur un tableau, dans les exemples vus precedemment: // iterateur sur les proprietes de l'objet
let list = Object.keys(this.state.hobbies).map((key, index) => {
// key = element courant (propriete courante de l'objet)
consthobby = this.state.hobbies[key];
const liStyle = {
backgroundColor:index % 2 === 0 ? 'lightpink' : 'red'
};
return <li key={key} style={liStyle} onClick={() => this.removeHobby(key)}>{hobby}</li>
});
ETAPE 2 : on va devoir, comme pour les exemples faits avec vueJS, utiliser le "cycle de vie" du composant (https://reactjs.org/docs/react-component.html#the-component-lifecycle), et charger des données distantes depuis FireBase quand le composant est "monté", et aussi fermer la connexion quand il est "démonté". On va pour cela définir les méthodes App.js : componentWillMount() { console.log("Will mount") // this runs right before the <App> is rendered } componentWillUnmount() { console.log("Will unmount") } Implémentez ces méthodes et vérifiez bien qu'elles sont appelées... ETAPE 3 : on va créer une base sur FireBase
ETAPE 4 : on ajoute au projet le code pour se connecter à la base: Dans votre projet, au même niveau que index.js, créez un fichier base.js, et mettez ceci dedans (attention a copier/coller les infos depuis le site, pour que cela corresponde à VOTRE BD) import Rebase from 're-base'; const base = Rebase.createClass({ // copier les 3 premières lignes de VOTRE config de votre base !!! // NE PRENEZ PAS LES VALEURS QUI SONT ICI !!! apiKey: "AIzaSyCW_WJJb16YVDlsdsd9c0YNNGnfdssorzWGFRU2ScU", authDomain: "react-mbds-firebase.firebaseapp.com", databaseURL: "https://react-mbds-firebase.firebaseio.com" // pas de , à la fin }); export default base; ETAPE 5 : on ajoute le module npm re-base pour "parler à firebase" On ajoute une ligne au fichier package.json pour installer la lib npm qui va bien: "dependencies": { "react": "^16.1.1", "react-dom": "^16.1.1", "react-scripts": "1.0.17", "re-base": "2.2.0"// -> ajouter cette ligne, mettez bien 2.2.0 ! }, Faites "npm install", ça va installer re-base dans node_modules ETAPE 6 : on va utiliser re-base pour synchroniser l'état du composant, c'est-à dire les hobbies: Dans App.js: .... import base from './base'; .... componentWillMount() { //alert("toto") // this runs right before the <App> is rendered this.ref = base.syncState("hobbies", { context: this, state: 'hobbies' }); } componentWillUnmount() { base.removeBinding(this.ref); } Etape 7 : testez ! Sauvez, testez. Ouvrez dans un onglet votre base et regardez les données en sync. Ouvrez deux onglets avec l'appli React, regardez... Correction
Séance 4 - présentation de NodeJS et premiers exercices simples
Ressource : des MOOCS!
Outils à installer
Casablanca : exemples JsBin sur les objets JavaScript, fait en cours: http://jsbin.com/nemaxonani/edit?js,console TP - routage avec le module ExpressJS, Web Services RESTFULSupports de cours: transparents de présentation de Express
TP - MongoDB
1 - Installer MongoDB sur votre machineSuivez les installations propres à votre système d'exploitation situées sur cette page du site officiel. Ne choisissez pas l'installation manuelle. Une fois installé lancez la commande "mongod" en ligne de commande. Si le daemon mongoDB ne se lance pas, regardez les erreurs. Sur mon Mac j'ai fait:
2 - Créer et peupler une collection par défaut (avec un dataset issu du tutorial MongoDB officiel)
3 - Installer un outil d'administration sympaJe vous recommande fortement MongoChef, un produit commercial mais gratuit pour utilisation non commerciale. Le télécharger sur: https://studio3t.com/ 4 - Ouvrir 3T STudio et voir la collection que l'on vient d'importer
Quelques screenshots:
5 - Installer le driver MongoDB pour NodeJS
6 - Tester des requêtes CRUD avec NodeJS et expressFAIT EN LIVE CODING: inserer + supprimer des lignes d'une table HTML depuis JavaScript: http://jsbin.com/hinilet/edit?console,output
A FAIRE : essayer d'ajouter un findByName et un count à l'application précédente. Corrections pour le count et pour le findByName: Voir la doc de MongoDB pour les requêtes comprenant des expressions régulières: https://docs.mongodb.com/manual/refe...r/query/regex/ Dans serverCrudWithMongo.js: // ICI c'est autorisé par la norme REST car // "count" est un mot réservé, on ne risque pas de // le prendre pour une TABLE ou une collection // cf la partie "reserved words" de // https://blog.octo.com/designer-une-api-rest/ app.get('/api/restaurants/count', function(req, res) { // on renvoie le nombre de restaurants mongoDBModule.countRestaurants(function(data) { var objdData = { msg:"Count effectué avec succès", data: data } res.send(JSON.stringify(objdData)); }); }); // On va récupérer des restaurants par un GET (standard REST) // cette fonction d'API peut accepter des paramètres // pagesize = nombre de restaurants par page // page = no de la page // Oui, on va faire de la pagination, pour afficher // par exemple les restaurants 10 par 10 app.get('/api/restaurants', function(req, res) { // Si présent on prend la valeur du param, sinon 1 let page = parseInt(req.query.page || 0); // idem si present on prend la valeur, sinon 10 let pagesize = parseInt(req.query.pagesize || 10); let nom = req.query.nom; if(nom) { // find by name mongoDBModule.findRestaurantsByName(nom, page, pagesize, function(data) { var objdData = { msg:"restaurant recherchés par nom avec succès", data: data } res.send(JSON.stringify(objdData)); }); } else { // find normal mongoDBModule.findRestaurants(page, pagesize, function(data) { var objdData = { msg:"restaurant recherchés avec succès", data: data } res.send(JSON.stringify(objdData)); }); } }); Dans app_modules/crud-mongo.js: exports.countRestaurants = function(callback) { console.log("DANS COUNT") MongoClient.connect(url, function(err, client) { var db = client.db(dbName); db.collection('restaurants') .count(function(err, res) { console.log("COUNT = " + res) callback(res); }); }); }; exports.findRestaurantsByName = function(nom,page, pagesize, callback) { MongoClient.connect(url, function(err, client) { var db = client.db(dbName); console.log("pagesize = " + pagesize); console.log("page = " + page); console.log("FIND BY NAME nom=" + nom); // syntaxe recommandée // Cf doc mongodb: https://docs.mongodb.com/manual/reference/operator/query/regex/ // The $regex value needs to be either the string // pattern to match or a regular expression object. // When passing a string pattern, you don't include // the / delimitters // VERSION avec $regexp et $options let myquery = { "name": { $regex: ".*" + nom + ".*", $options:"i" } } // VERSION avec objet RegExp //let myquery = {'name' : new RegExp('^.*'+nom+'.*$',"i")}; // ou, si on veut être "case sensitive" //let myquery = {'name' : new RegExp('^.*'+nom+'.*$')}; if(!err){ db.collection('restaurants') .find(myquery) .skip(page*pagesize) .limit(pagesize) .toArray() .then(arr => callback(arr)); } else{ callback(-1); } }); }; Suite de l'étude de Réact : liaison avec Node/MongoDBRessources externes :
Travailler avec les restaurants et la base MongoDB
Si vous voulez ajouter le support "cross domain" à votre projet node/MongoDBAjouter les lignes suivantes dans la configuration de votre serveur (fichier serverCrudWithMongo.js), ça se passe dans la configuration de express, c'est l'équivalent des "Servlet Filters" en JavaEE : app.use(function (req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE »); next(); }); Travail à faire (à rendre et noté) : refaire l'application VueJS qui fait le CRUD sur les restaurants, mais en ReactVous commencerez pas simplement afficher des restaurants dans une table. Peu importe si ce n'est pas joli... On utilisera un tableau de restaurants dans le "state" de React en s'inspirant des exemples vus précédemment avec les hobbies. On utilisera la méthode componentDidMount() pour faire un fetch sur les restaurants: componentDidMount() { console.log("Composant avant premier affichage") // ici aller chercher des données dans une source de données (ex: GET /api/restaurants } Si vous avez récupéré le livre recommandé au début de cette section, il y a un chapitre qui s'intitule "Aller chercher les données" qui montre des exemples d'utilisation de fetch en React. Premiers pas avec Angular (4/5)1 : création d'une application "squelette"
2 : affichage d'une liste d'éléments
3 : création d'un nouveau composant
import { Component, Input } from "@angular/core"; @Component ({ selector: 'app-username', template:` <p>{{username}}</p> ` }) export class UsernameComponent { @Input() username :string; } Remarquez qu'on n'a pas utilisé ici de template html séparé, à la place on a mis le template directement sous forme de chaine de caractère entre les caractères `....` Le Maintenant, ajoutez des instances de ce composant dans le template app.components.html: <app-username [username]="'Michel'"></app-username> <app-username [username]="'John'"></app-username> Regardez ce que cela donne.... Regardez aussi le fichier Maintenant on veut pouvoir cliquer sur un nom et afficher un message dans le template du composant principal. On va faire comme en VueJS : envoyer un événement quand on clique sur le nom. 4 : définition d'un événement qui sera envoyé du composant "fils" vers le composant "père"
export class UsernameComponent { @Input() username :string; @Output() userClicked = new EventEmitter<string>(); // définition d'un événement onUsernameClicked() { this.userClicked.emit(this.username); // émission de l'événément } } Et dans le template ( template:` <p (click)="onUsernameClicked()">{{username}}</p> ` Ainsi, dans le template du composant ( <app-username [username]="'Michel1'" (userClicked)="onUserWasClicked($event)"></app-username> <app-username [username]="'John'" (userClicked)="onUserWasClicked($event)"></app-username> Et maintenant on peut écrire la méthode onUserWasClicked(username: string) { alert(username); } Testez l'application : en cliquant sur un nom, ça doit afficher une alerte avec la valeur associée. 5 : binding bi-directionnel avec [(ngModel)]="nom"
ICI UNE CORRECTION DES ETAPES PRECEDENTES (exemple fait en live). Dezippez, cd dans le repertoire, npm install puis ng serve --open 6 : Completer l'exemple des hobbies complet, mais en angularEn vous aidant de l'exemple précédent :
Démarrage du mini projetSujet proposé (mais j'accepte sujets persos)
Contraintes :
Hébergement sur HEROKU.COMExemples d'applications prêtes à déployer sur Heroku (regardez les README.txt pour les explications)
Mots clés:
|
Powered by MindTouch Deki Open Source Edition v.8.08 |