Skip to content
Snippets Groups Projects
Commit 90203c2b authored by Thomas Fritsch's avatar Thomas Fritsch
Browse files

maj readme

suppression plugin-proposal-class-properties inutile désormais
wording
mise en forme
synchro cours react
parent 756346a4
Branches
No related tags found
No related merge requests found
......@@ -53,6 +53,8 @@ Il va vous servir de base pour ce nouveau TP.
## A.2. Configuration de Prettier
<img src="images/readme/header-prettier.jpg" />
_**Lors du précédent TP, vous avez en principe installé l'extension Prettier dans VSCodium.**_
Prettier est un formateur de code automatique qui est le plus populaire à l'heure actuelle dans l'écosystème JavaScript.
......@@ -69,7 +71,7 @@ Prettier est un formateur de code automatique qui est le plus populaire à l'heu
}
}
```
Créez ensuite un fichier `.prettierrc` à la racine du TP :
2. **Créez ensuite un fichier `.prettierrc`** à la racine du TP :
```json
{
"singleQuote": true,
......@@ -79,11 +81,11 @@ Prettier est un formateur de code automatique qui est le plus populaire à l'heu
"arrowParens": "avoid"
}
```
Enfin, installez le paquet npm `prettier` dans le projet (_nécessaire pour que l'extension fonctionne_) :
3. **Enfin, installez le paquet npm `prettier`** dans le projet (_nécessaire pour que l'extension vscodium fonctionne_) :
```bash
npm install --save-dev prettier
```
Avec cette configuration, vos fichiers JS seront maintenant automatiquement formatés à chaque sauvegarde !
Avec cette configuration, vos fichiers JS seront maintenant automatiquement formatés à chaque sauvegarde ! Plus besoin de vous tracasser avec les retours à la ligne, les tabulations, les espaces, tout sera géré automatiquement par Prettier !
> _**NB :** si vous souhaitez en savoir plus sur la liste des configurations possibles, rendez vous sur https://prettier.io/docs/en/configuration.html_
......@@ -141,7 +143,7 @@ Comme dans le précédent TP lancez un serveur HTTP et la compilation du projet
**Lors du précédent TP nous avons créé un fichier `package.json` dans le projet grâce à la commande `npm init`.**
Ce fichier sert à plusieurs choses et notamment :
1. **Il permet de conserver l'historique de tous les paquets qui sont installés dans le projet.** C'est en quelque sorte l'équivalent du fichier `pom.xml` de maven. Vérifiez que dans la section `devDependencies` sont bien listés les paquets suivants :
1. **Il permet de conserver l'historique de tous les paquets qui sont installés dans le projet.** C'est en quelque sorte l'équivalent du fichier `pom.xml` en JAVA ou encore du `composer.json` en PHP. Vérifiez que dans la section `devDependencies` sont bien listés les paquets suivants :
- `@babel/cli`
- `@babel/core`
- `@babel/preset-env`
......@@ -154,7 +156,7 @@ Ce fichier sert à plusieurs choses et notamment :
> _**NB :** Le dossier **`node_modules` n'est jamais versionné** (c'est en général un dossier relativement volumineux) mais le **`package.json` lui l'est** car il servira de "recette" pour indiquer aux développeurs qui rejoindraient le projet quels sont les paquets nécessaires._
>
> _En effet, grâce au `package.json`, un nouveau développeur n'a qu'à exécuter la commande `npm install` (sans préciser de nom de paquet) pour installer automatiquement toutes les dépendances du projet (c'est d'ailleurs ce que vous avez fait plus haut) !_
> _En effet, grâce au `package.json`, un nouveau développeur n'a qu'à exécuter la commande `npm install` (sans préciser de nom de paquet) pour installer automatiquement toutes les dépendances du projet (c'est d'ailleurs ce que vous avez fait au début du TP) !_
2. **Dans ce fichier on va également pouvoir ajouter des "scripts personnalisés" que l'on pourra lancer à l'aide de la commande `npm run xxxxx`.** C'est cette dernière possibilité que l'on va maintenant exploiter pour nous simplifier la vie dans la suite du TP.
......@@ -169,7 +171,7 @@ ou
./node_modules/.bin/babel src -d build --verbose --watch --source-maps
```
Avec le `package.json` **on va créer des "raccourcis" pour lancer ces commandes plus facilement.**
Grâce au `package.json` **on va créer des "raccourcis" pour lancer ces commandes plus facilement.**
1. **Stoppez d'abord la commande "./node_modules/.bin/babel ... --watch ..." que vous aviez lancée au point A.3.2.**
2. Dans VSCodium, **ouvrez le fichier `package.json`** en tapant <kbd>CTRL</kbd>+<kbd>P</kbd> puis le nom du fichier ( <kbd>Enter</kbd> _pour ouvrir le fichier_)
3. **Localisez la section "scripts" du fichier**. Elle doit ressembler à :
......@@ -215,8 +217,8 @@ Avec le `package.json` **on va créer des "raccourcis" pour lancer ces commandes
<img src="images/readme/npm-run-watch.gif" />
Vous voyez que le watch ne vous rend pas la main sur le terminal, il faut le laisser ouvert pour que la recompilation automatique à chaque sauvegarde continue de fonctionner.
Vous voyez que le watch ne vous rend pas la main sur le terminal, il faut en effet le laisser ouvert car il va permettre de recompiler automatiquement à chaque fois que vous modifierez un fichier ! Essayez de modifier le contenu du fichier main.js, vous verrez que la compilation se relance toute seule !
## Étape suivante <!-- omit in toc -->
Si la compilation fonctionne, vous pouvez passer à l'étape suivante : [B. La POO](B-poo.md)
\ No newline at end of file
Maintenant que votre code compile, vous pouvez passer à l'étape suivante : [B. La POO](B-poo.md)
\ No newline at end of file
......@@ -2,19 +2,22 @@
# B. POO <!-- omit in toc -->
_**Nous allons développer dans ce TP une classe `Component` qui va permettre de générer du code HTML en JS.**_
A chaque étape du TP vous allez perfectionner la classe Component pour la rendre capable de gérer des paramètres supplémentaires.
> _**NB :** Dans ce TP vous coderez dans un premier temps vos classes directement dans le fichier `src/main.js` **sans compiler** votre code et **sans passer par des fichiers (modules) séparés**._
>
> _Dans la suite du TP on compilera notre code pour le rendre compatible avec tous les navigateurs, et on organisera notre code plus proprement en séparant les classes dans des modules différents._ \
> _Mais pour le moment on va simplifier la mise en place en remettant ça à plus tard (ne faites pas ça dans la vraie vie !)._
## Sommaire <!-- omit in toc -->
- [B.1. Rappels de syntaxe](#b1-rappels-de-syntaxe)
- [B.1.1. class & propriétés publiques](#b11-class-propriétés-publiques)
- [B.1.2. méthodes](#b12-méthodes)
- [B.2. Support des syntaxes modernes](#b2-support-des-syntaxes-modernes)
- [B.3. La classe Component](#b3-la-classe-component)
- [B.2. La classe Component](#b2-la-classe-component)
- [B.4. Héritage : La classe Img](#b4-héritage-la-classe-img)
**NB : Dans ce TP vous coderez dans un premier temps vos classes directement dans le fichier `src/main.js` sans passer par des fichiers (modules) séparés.**
Dans la suite du TP on organisera notre code plus proprement en séparant les classes dans des modules différents.
Mais pour le moment on va simplifier la mise en place en remettant ça à plus tard (*ne faites pas ça dans la vraie vie !*).
## B.1. Rappels de syntaxe
### B.1.1. class & propriétés publiques
......@@ -42,9 +45,9 @@ class Character {
}
}
```
Attention cependant, cette notation n'est **pas encore dans la spec officielle** d'EcmaScript (_la spec suivie par JavaScript_) mais a des chances d'être intégrée dans la version 2021 d'EcmaScript (ES12) : cf. https://github.com/tc39/proposal-class-fields et https://tc39.github.io/proposal-class-fields/
Attention cependant, cette notation n'est **pas encore dans la spec officielle** d'EcmaScript (_la spec suivie par JavaScript_) mais devrait être intégrée dans la version 2022 de la spec (ES13) : cf. https://github.com/tc39/proposals/blob/master/finished-proposals.md et https://github.com/tc39/notes/blob/HEAD/meetings/2021-04/apr-19.md#class-fields-private-methods-and-static-class-features-for-stage-4
Pour pouvoir l'utiliser, il faudra modifier légèrement la configuration de Babel (cf. chapitre suivant).
Ceci dit, Babel permet déjà de l'utiliser !
### B.1.2. méthodes
La création de méthodes d'une classe se fait de la manière suivante :
......@@ -67,52 +70,9 @@ heisenberg.fullName();
```
## B.2. Support des syntaxes modernes
**Comme vu dans le [chapitre précédent](#b11-class-propriétés-publiques), certaines syntaxes que nous allons utiliser dans le TP ne sont pas encore dans la spec officielle** (_c'est le cas pour la déclaration de propriétés d'instance en dehors du constructeur, les propriétés ou méthodes privées ou encore les propriétés et méthodes statiques_).
Ces fonctionnalités du langages sont **dans un stade relativement avancé de discussion (niveau 3 sur 4)** et ont désormais de grandes chances d'arriver dans la spécification officielle prochainement. Pas de raison de s'en priver donc.
Pour pouvoir utiliser ces syntaxes, nous allons **modifier la configuration de Babel** qui par défaut n'est capable de compiler que les syntaxes officielles :
1. **Installez le paquet npm ["@babel/plugin-proposal-class-properties"](https://babeljs.io/docs/en/babel-plugin-proposal-class-properties)** :
```bash
npm install --save-dev @babel/plugin-proposal-class-properties
```
2. **Modifiez le fichier `.babelrc`** pour y ajouter le plugin que l'on vient d'installer :
```json
{
"presets": ["@babel/env"],
"plugins": ["@babel/plugin-proposal-class-properties"]
}
```
3. **Stoppez puis relancez la compilation à l'aide de la commande `npm run watch`** et vérifiez qu'aucune erreur n'est remontée dans le terminal.
## B.2. La classe Component
4. **Copiez-collez le code suivant directement dans le fichier `main.js`** :
```js
class Character {
firstName;
lastName;
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
const heisenberg = new Character('Walter', 'White');
console.log(
heisenberg.firstName,
heisenberg.fullName(),
);
```
Vérifiez que la syntaxe employée pour la déclaration des propriétés `firstName` et `lastName` sont correctement prises en compte par le compilateur et que le `console.log` affiche bien les bonnes valeurs dans la console.
***Si c'est bon, vous êtes prêt pour la suite !***
## B.3. La classe Component
1. **Effacez le code que vous aviez copié/collé dans l'exercice précédent** (_ne conservez que le tableau `data`_)
2. **Dans le fichier `src/main.js` créez une classe `Component` qui s'utilise de la manière suivante :**
1. **Dans le fichier `src/main.js` créez une classe `Component` que vous utiliserez de la manière suivante :**
```js
const title = new Component( 'h1' );
document.querySelector('.pageTitle').innerHTML = title.render();
......@@ -134,6 +94,10 @@ Pour pouvoir utiliser ces syntaxes, nous allons **modifier la configuration de B
**Vérifiez que votre classe fonctionne correctement en inspectant le code généré par votre application avec l'Inspecteur d'éléments des devtools du navigateur.**
> _**NB :** On passe par l'inspecteur d'éléments car visuellement à l'écran, c'est difficile de contrôler le rendu : rien ne s'affiche car on n'a pas précisé de contenu au `<h1>` !_
<img src="images/readme/pizzaland-01-h1.png" />
3. **Ajoutez un second paramètre au constructeur, nommé `children`.** Modifiez le code de la méthode render() de manière à ce que le code suivant :
```js
const title = new Component( 'h1', 'La carte' );
......@@ -152,19 +116,21 @@ Pour pouvoir utiliser ces syntaxes, nous allons **modifier la configuration de B
```js
const img = new Component( 'img' );
```
`render()` doit retourner `<img />` et pas `<img></img>` (_car ce n'est pas un code HTML valide selon la spec du W3C_).
`render()` doit retourner `<img />` (_une balise "auto fermante", c'est à dire sans enfants_) et pas `<img></img>` (_car ce n'est pas un code HTML valide selon la spec du W3C_).
**Testez votre classe comme ceci** :
```js
const img = new Component( 'img' );
document.querySelector( '.pageContent' ).innerHTML = img.render();
```
Vérifiez dans **l'inspecteur d'éléments** que votre image est bien ajoutée dans `pageContent`.
Vérifiez dans **l'inspecteur d'éléments** que votre image est bien ajoutée dans `pageContent` :
> _**NB :** On passe par l'inspecteur d'éléments car visuellement à l'écran, c'est difficile de contrôler le rendu : aucune image ne s'affiche car on n'a pas précisé ni de source ni de taille à l'image !_
> _**NB :** Comme tout à l'heure avec le `h1`, on passe par l'inspecteur d'éléments car visuellement à l'écran, c'est difficile de contrôler le rendu : aucune image ne s'affiche car on n'a pas précisé ni de source ni de taille à l'image !_
> _**NB2 :** Selon votre navigateur il est possible que l'inspecteur d'éléments n'affiche que `<img>` et pas `<img />`. C'est une simplification faite par les devtools, mais ça ne veut pas dire que votre code ne fonctionne pas. Testez donc votre code avec `console.log(img.render())`, là vous saurez avec certitude si votre méthode retourne bien `<img />`._
<img src="images/readme/pizzaland-02-inspecteur.png" >
5. **Ajoutez un paramètre `attribute` en 2e position du constructeur de la classe `Component` : enregistrez ce paramètre dans une propriété d'instance `this.attribute`.**
La signature du constructeur sera désormais :
......
......@@ -50,8 +50,7 @@ Nous verrons plus tard dans le TP comment rendre nos modules compatibles avec le
{
"presets": [
["@babel/env", {"modules": false}]
],
"plugins": ["@babel/plugin-proposal-class-properties"]
]
}
```
Pour prendre en compte la nouvelle configuration de Babel, **stoppez (<kbd>CTRL</kbd>+<kbd>C</kbd>) puis relancez** la compilation à l'aide de la commande `npm run watch`
......@@ -89,7 +88,7 @@ Nous verrons plus tard dans le TP comment rendre nos modules compatibles avec le
> export default function checkValue(value){...} // OK aussi !
> ```
2. **Compilez votre code et testez la page dans le navigateur** : le résultat doit être identique à celui obtenu précédemment :
4. **Compilez votre code et testez la page dans le navigateur** : le résultat doit être identique à celui obtenu précédemment :
<img src="images/readme/pizzaland-02.png" >
......@@ -137,7 +136,7 @@ Comme vu en cours, le bundler le plus employé en JS est [Webpack](https://webpa
}
]
},
devtool: 'source-map'
devtool: 'cheap-source-map'
}
```
......
......@@ -19,7 +19,7 @@ _**L'objectif de cet exercice est d'utiliser une classe à l'intérieur d'une au
1. **Modifiez le code de la méthode `render()`** de la classe `Component` pour lui permettre de recevoir dans le paramètre `children` :
- soit une **chaîne de caractères** (comme c'est déjà le cas actuellement)
- soit un **tableau de chaînes de caractères.** <br>Par exemple : si `tag` vaut `"div"` et que `children` vaut `[ "youpi", "ça", "marche" ]` alors `render()` retournera la chaîne `"<div>youpiçamarche</div>"`.
- soit un **tableau de chaînes de caractères.** <br>Par exemple : si `tagName` vaut `"div"` et que `children` vaut `[ "youpi", "ça", "marche" ]` alors `render()` retournera la chaîne `"<div>youpiçamarche</div>"`.
> _**NB :** Pour ne pas alourdir trop le code de la méthode `render()` et pour avoir un code plus lisible, passez le code de rendu des enfants, dans une méthode `renderChildren()`._
......@@ -90,6 +90,10 @@ _**L'objectif de cet exercice est d'utiliser une classe à l'intérieur d'une au
on **surcharge juste le constructeur** en invoquant celui de `Component` (`super(...)`)
et en lui passant les bons `tagName`, `attribute` et `children`.
> _**Attention :** Je pense que vous l'aurez remarqué, le code que je vous ai fourni pour cette classe `PizzaThumbnail` n'est **pas hyper pratique ni lisible** : elle a une utilité dans notre exercice mais ce n'est pas un fonctionnement que je recommande dans la vraie vie ou dans vos futurs projets !_
>
> _Plutôt que d'imbriquer des `Component` dans des `Component` comme on le fait ici, on aurait pu par exemple **overrider simplement la méthode `renderChildren()`** pour lui faire retourner une **template string** contenant tout le code HTML._
Dans le `src/main.js`, testez votre classe avec le code suivant :
```js
const pizza = data[0];
......@@ -152,7 +156,7 @@ naviguer d'une page à l'autre sans rechargement de page !
(_principe de base des [SPA](https://en.wikipedia.org/wiki/Single-page_application)_)
### D.3.1 Rappels de syntaxe
Pour rappel les propriétés et méthodes statiques peuvent se déclarer à l'aide du mot clé `static`. Ces propriétés/méthodes sont définies et s'utilisent au niveau de la classe (et pas de l'instance) comme ceci :
Pour rappel les propriétés et méthodes statiques peuvent se déclarer à l'aide du mot clé `static`. Ces propriétés/méthodes n'existent qu'au niveau de la classe (et pas de l'instance) et s'utilisent comme ceci :
```js
class Counter {
......@@ -208,12 +212,12 @@ class Character {
}
```
Le support des propriétés et méthodes privées est en stage 3/4 de spécification. Ce n'est donc pas encore dans la spec EcmaScript officielle. Néanmoins il est possible de les utiliser grâce au plugin Babel [@babel/plugin-proposal-class-properties](https://babeljs.io/docs/en/babel-plugin-proposal-class-properties) que l'on a déjà installé précédemment (c'est le même que pour les propriétés publiques).
Comme les propriétés publiques, le support des propriétés et méthodes privées n'est pas encore dans la spec officielle mais devrait être intégré à ES2022 (ES13). Néanmoins il est possible de les utiliser grâce au `preset-env` qui inclue ces syntaxes.
> _**NB :** Si vous vous demandez pourquoi on écrit `#propriete` et pas `private propriete` comme dans d'autres langages, la réponse se trouve ici :_ https://github.com/tc39/proposal-class-fields/blob/master/PRIVATE_SYNTAX_FAQ.md#why-arent-declarations-private-x
### D.4.2. Rappels getters/setters
Vous pouvez déclarer des getter et des setters de la façon suivante :
Vous pouvez déclarer des getter et des setters de la manière suivante :
```js
class Character {
......@@ -243,5 +247,6 @@ Router.routes = [{ path: '/', page: pizzaList, title: 'La carte' }];
Router.navigate('/'); // affiche une page vide
pizzaList.pizzas = data;
Router.navigate('/'); // affiche la liste des pizzas
```
**C'est la fin de ce TP, rendez-vous très vite pour le prochain chapitre !**
images/readme/header-prettier.jpg

22.8 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment