# Frameworks Javascript - Tour d'horizon ## William Petit - S.C.O.P. Cadoles --- ## Les frameworks ## RiotJS ## ReactJS ## EmberJS --- ## RiotJS ### Présentation générale ### Concepts généraux ### Exercice --- ## Présentation générale (1) - Publication: Septembre 2013 - Mainteneurs principaux: [@GianlucaGuarini](https://github.com/GianlucaGuarini) et [@tipiirai](https://github.com/tipiirai) (projet communautaire) - License: MIT --- ## Présentation générale (2) |Avantages|Inconvénients| |:-|:-| |Une librairie et pas un framework| Une librairie et pas un framework| | Projet communautaire | Projet communautaire | | Orientée "composant" | | | API minimaliste | | Prêt à l'emploi (pas de transpilage nécessaire en développement) | | Routeur "frontend" disponible | --- ## Concepts généraux ### Composants ("tags") ### Observable --- ## Composants ### Structure et utilisation d'un composant ### Templating ### Styles de composant ### Évènements du DOM ### Cycle de vie du composant --- ## Structure d'un composant ```html { opts.foo } ``` --- ## Utilisation du composant ### Compilation dans le navigateur ```html ``` --- ## Templating ```html { foo } foo est égal à "bar" ! ``` --- ## Styles de composant ### Feuille de style ### Styles et classes dynamiques --- ## Feuille de style ```html Foo
Bar
``` --- ## Styles et classes dynamiques ```html Foo
Bar
``` --- ## Évènements du DOM ```html ``` --- ## Cycle de vie du composant ```html ``` --- ## Observable (1) ### Déclaration d'un "service" ```javascript // services/auth.js class MyAuthService { constructor() { riot.observable(this) this.user = null; } login(user, password) { var form = new FormData(); form.append('login', login); form.append('password', password); return fetch('/login', { method: 'POST', form: form }) .then(res => res.json()) .then(user => { this.user = user; this.trigger('loggedIn', user); }) ; } isLoggedIn() { return this.user != null; } } const myAuth = new MyAuthService(); ``` --- ## Observable (2) ### Utilisation du service ```html ``` --- ## Exercice Implémenter une application minimaliste de gestion de tâches avec Riot. Cette application doit comprendre les fonctionnalités suivantes: - Ajouter une nouvelle tâche (champs texte) avec une priorité parmi les suivantes: "haute", "moyenne", "basse" et un statut: "en cours" ou "terminé" - Marquer une tâche comme "terminée". - Afficher la liste des tâches en attente, triées par priorité décroissante + tâches terminées en dernier. - Les tâches doivent être persistées dans le "Local Storage" du navigateur. --- ## ReactJS ### Présentation générale ### Concepts généraux ### Prise en main --- ## Présentation générale (1) - Publication: Mars 2013 - Mainteneur principal: Facebook - License: MIT --- ## Présentation générale (2) |Avantages|Inconvénients| |:-|:-| |Grande communauté, très active | Changement de license puis rétropédalage en 2017 | | Maintenu et utilisé par Facebook en interne | Nécessité de mettre en place un pipeline de transpilage | | Architecture Flux | Architecture Flux | | Possibilité de faire des applications "isomorphiques" avec NodeJS | | "React Native" | | API stable | | Virtual DOM | | Moteurs "lightweight" compatibles | --- ## Concepts généraux ### Composants ### L'architecture Flux --- ## Composants ### Structure d'un composant ### Props ### State ### Évènements du DOM ### Cycle de vie d'un composant --- ## Structure d'un composant ```jsx // components/hello-world.js import React from 'react' class HelloWorld extends React.Component { render() { return (

Hello World

Welcome to React

) } } export default HelloWorld ``` --- ## Props ```jsx // components/props-example.js import React from 'react' class PropsExample extends React.Component { render() { return ( { this.props.text } ) } } export default PropsExample // app.js import React from 'react' import ReactDOM from 'react-dom' import PropsExample from './components/props-example' const mountpoint = document.getElementById('props-example'); ReactDOM.render(, mountpoint) ``` --- ## State ```jsx // components/clock.js import React from 'react' class Clock extends React.Component { constructor(props) { // On fait appel au constructeur de la classe // parente super(props) // Initialisation du "state" du composant this.state = { time: new Date() } // On appelle la méthode tick() du composant // toutes les secondes setInterval(this.tick.bind(this), 1000); } // Méthode de rendu du composant render() { return (
Time: { this.state.time.toString() }
) } // La méthode tick() met à jour le state du composant avec // la date courante tick() { this.setState({ time: new Date() }); } } export default Clock ``` --- ### Évènements du DOM ```jsx // components/counter.js import React from 'react' class Counter extends React.Component { constructor(props) { // On fait appel au constructeur de la classe // parente super(props) // Initialisation du "state" du composant this.state = { count: 0 } } // Méthode de rendu du composant render() { return (
Count: { this.state.count } 
) } // La méthode increment() incrémente la valeur du compteur de 1 increment() { this.setState(prevState => ({ count: prevState.count+1 })) } // La méthode decrement() incrémente la valeur du compteur de 1 decrement() { this.setState(prevState => ({ count: prevState.count-1 })) } } export default Counter ``` --- ## Cycle de vie d'un composant ``` // components/clock-lifecycle.js import React from 'react' class Clock extends React.Component { constructor(props) { super(props) this.state = { time: new Date() } } componentDidMount() { console.log('mount') this.intervalId = setInterval(this.tick.bind(this), 1000); } componentWillUnmount() { console.log('unmount') clearInterval(this.intervalId); } render() { return (
Time: { this.state.time.toString() }
) } tick() { this.setState({ time: new Date() }); } } export default Clock ``` --- ## L'architecture Flux ![center](./img/flux-simple-f8-diagram-with-client-action-1300w.png) --- ## Exercice Implémenter une application minimaliste de gestion de tâches avec React (sans l'architecture Flux). Cette application doit comprendre les fonctionnalités suivantes: - Ajouter une nouvelle tâche (champs texte) avec une priorité parmi les suivantes: "haute", "moyenne", "basse" et un statut: "en cours" ou "terminé" - Marquer une tâche comme "terminée". - Afficher la liste des tâches en attente, triées par priorité décroissante + tâches terminées en dernier. - Les tâches doivent être persistées dans le "Local Storage" du navigateur. --- ## EmberJS ### Présentation générale ### Concepts généraux ### Initialisation d'un projet ### Exercice --- ## Présentation générale (1) - Publication: Décembre 2011 - Mainteneur principal: [Ember Core Team](https://emberjs.com/team/) (projet communautaire) - License: MIT --- ## Présentation générale (2) |Avantages|Inconvénients| |:-|:-| |"Clés en main"|"Opiniatre"| |API stable|Structure MVC classique| |Long-term support (1 an)| |Documentation exhaustive| |Ember Data| --- ## Concepts généraux ### Ember CLI ### Routes ### Templates ### Modèles ### Contrôleurs ### Composants --- ## Ember CLI ### Générer une nouvelle application ```shell npm install ember-cli -g ember new my-app cd my-app ember serve ``` --- ## Routes ### Générer une nouvelle route ```shell ember generate route foo ``` --- ## Templates ```handlebars {{!-- Interpolation de variable --}} {{ myVar }} {{!-- Utilisation d'un "helper" --}} {{helper params... }} {{!-- Définition d'un "block" --}} {{#block params... }} ... {{/block}} ``` --- ## Modèles ### Générer un nouveau modèle ```shell ember generate model bar ``` --- ## Exercice Implémenter une application minimaliste de gestion de tâches avec EmberJS. Cette application doit comprendre les fonctionnalités suivantes: - Ajouter une nouvelle tâche (champs texte) avec une priorité parmi les suivantes: "haute", "moyenne", "basse" et un statut: "en cours" ou "terminé" - Marquer une tâche comme "terminée". - Afficher la liste des tâches en attente, triées par priorité décroissante + tâches terminées en dernier. - Les tâches doivent être persistées dans le "Local Storage" du navigateur. --- # Licence ## CC BY-NC-SA 3.0 FR [Creative Commons - Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 3.0 France](https://creativecommons.org/licenses/by-nc-sa/3.0/fr/)