JavaScript

 

Vincent Garreau

 

Slides disponibles sur
slides.com/vincentgarreau

Initiation au JavaScript : outils et astuces pour un développement front-end moderne

H1 à H5 / P2015

vincentgarreau.com

Au programme

Lundi 13/11 Workflow CSS + Les bases du JavaScript
Mardi 14/11 Workflow JavaScript / Modules et composants web
Mercredi 15/11 (1) Frameworks JavaScript / Initiation à Vue.js
Mercredi 15/11 (2) Frameworks JavaScript / Initiation à Vue.js + Consignes TP1
Jeudi 16/11 Correction TP1 + Suite initiation à Vue.js + Consignes TP2
Jeudi 7/12 Correction TP2 + Récapitulatif global du cours

18 heures avec vous ! (6 x 3 heures)

Workflow CSS

Intervention 1/6 - Lundi 13/11

Les bases du CSS

Préprocesseurs CSS

Postprocesseurs CSS

Méthodologies CSS

 

Les bases du JavaScript

Intervention 1/6 - Lundi 13/11

Variables

Opérations

Conditions

Boucles

Fonctions

Interaction avec le DOM

Événements

L'objet window

 

Workflow JavaScript
Modules et composants web

Intervention 2/6 - Mardi 14/11

Package managers

Linters JavaScript

Modules et composants web

Systèmes de modules

Module bundlers

Frameworks JavaScript
Introduction à Vue.js

Intervention 3+4+5+6/6 - Mercredi 15/11 au Jeudi 07/12

Présentation rapide des frameworks JavaScript actuels

Introduction à Vue.js

Workflow CSS

Les bases du

CSS

Comment ajouter du CSS ?

<style>.element { width: 200px; }</style>  
<span style="width:200px"></span>
<link rel="stylesheet" href="style.css">

Internal style

Inline style

External style

Les sélecteurs CSS ont un poids qui détermine un ordre de priorité

 

Terme en anglais : CSS specificity

Terme en français : Poids des sélecteurs

<span style="color: red"> // 1000

#element // 100

.element // 10

span // 1

#element > div > li:hover // 100 + 1 + 1 + 10

.element !important // S'applique en priorité
Style inline
(HTML)

IDs
Classes, attributs,
pseudo classes (:)
Elements,
pseudo elements
(::)
1000 100 10 1

En CSS, on évite de se répéter

DRY :

Don't Repeat Yourself

cela dit...

 

KISS :

Keep It Simple, Stupid

.button-push { padding: 10px; }
<button class="button-push">Push 1</button>
<button class="button-push">Push 2</button>

.classes = réutilisables 👍🏻

#ids = uniques

 

D'après les standards W3C

Le  CSS doit être le plus

maintenable possible

💪

Préprocesseurs CSS

Un préprocesseur CSS contient une palette d'outils qui permet d'écrire un CSS plus maintenable

Plusieurs
préprocesseurs CSS
existent

 

Less

 

Sass

 
Stylus

Stylus

// CSS
.element {
  width: 200px;
  height: 80px;
  font-size: 1.2em;
}

// Stylus ({}, : et ; sont chacun optionnel)
.element
  width 200px
  height 80px
  font-size 1.2em

Léger et rapide à écrire

Stylus

// CSS
.element > li { padding:10px; }
.element > li:hover { padding:20px; }

// Stylus
.element
  > li
    padding 10px
    &:hover
      padding 20px

Principe d'indentation (évitez plus de 3 niveaux)

Variables

// Sans préprocesseur
.element
  width 20px
  height 20px
  margin-right 10px

// Avec préprocesseur
$element-size = 20px
.element
  width $element-size
  height $element-size
  margin-right $element-size / 2 // Opération

De nombreuses fonctionnalités

sont disponibles selon les préprocesseurs...

Mixins
Fonctions
Opérateurs

Conditions

Itérations

@extend

@block

....

Postprocesseurs CSS

Un postprocesseur CSS est un outil qui permet d'effectuer
des tâches spécifiques sur un fichier CSS

Exemple d'outil : PostCSS

 

PostCSS est un outil JavaScript qui permet d'effectuer des transformations d'un fichier CSS grâce à des plugins

 

Plugins PostCSS populaires :

autoprefixer : préfixe les propriétés

cssnext : permet d'écrire dès aujourd'hui du CSS4

Méthodologies CSS

Ensemble de conseils et de lignes de conduite

pour un CSS organisé et maintenable 

Catégorisation / Structure

 

Avantage d'un préprocesseur CSS :

 

Pouvoir générer un fichier CSS

à partir de plusieurs fichiers

 

Remarque

Sans préprocesseur, il est possible d'importer plusieurs fichiers CSS avec la méthode @import, mais cela est lourd car sans préprocesseur aucun fichier n'est généré.
Sans préprocesseur, 1 import = 1 requête HTTP en plus.

Exemple d'architecture CSS

7-1 Pattern
7 dossiers, 1 fichier

📁 base

📁 components

📁 layout

📁 pages

📁 themes

📁 abstracts

📁 vendors

main.scss

Convention de nommage

des classes

 

Permet d' éviter des cas problématiques comme écraser du style précédemment appliqué / mélanger des styles

 

Si plusieurs développeurs travaillent sur un même projet, appliquer une règle de  nommage  commune est  plus facile à comprendre / lire et à maintenir

Plusieurs conventions de nommage CSS existent

 

OOCSS  

Object-Oriented CSS


SMACSS  

Scalable and Modular Approach for CSS


BEM

Block Element Modifier

Convention de nommage

avec la méthodologie BEM

// block-name__element-name--modifier-name

<header class="app-header">
  <nav class="app-header-nav">
    <ul>
      <li class="app-header-nav__item"></li>
      <li class="app-header-nav__item app-header-nav__item--on"></li>
    </ul>
  </nav>
</header>

Block__Element--Modifier

Scoped CSS
&
CSS Modules

Les bases du
JavaScript

Qu'est ce que JavaScript ?

Un language de programmation très flexible

 

Ce n'est pas du Java ⚠️

 

Inventé par Brendan Eich, co-fondateur de Mozilla 🦊

À quoi sert JavaScript ?

Manipuler du HTML, du CSS, de la vidéo, dessiner...

 

Interagir avec des données via des APIs...

Créer des jeux vidéo...

 

Et bien d'autres choses !

Comment ajouter du JavaScript ?

<script>
  console.log('Hello World')
</script>
<script src="app.js"></script>

Dans <head></head>
ou
juste avant </body> (conseillé)

Variables

Déclarer une variable

// ES5 : var
var foo = 'bar'

// ES6 : let ou const
let foo = 'bar'
const foo = 'bar'

// Global (à éviter)
foo = 'bar'
window.foo = 'bar'

Quelles différences ?
let / const : let est modifiable, const ne l'est pas
var / let : "let is the new var", règles de portées
variable globale = accessible depuis l'objet window
Explications dans les slides suivantes

const / let : variables (non) modifiables

let age = 21
const firstname = 'Marie'
const identity = {}

age = 22 // let donc OK

firstname = 'Elodie' // const donc ERREUR

identity = { firstname: 'Marie' }  // ERREUR

identity.firstname = 'Marie' // OK

let = variable modifiable*
const  = variable non modifiable*
*non modifiable = non redéclarable

const company = 'Apple'

// Anciennement var (ES5)
if (company === 'Apple') {
  var founder = 'Steve Jobs'
}
console.log(founder) // Steve Jobs

// Avec let (ES6)
if (company === 'Apple') {
  let founder = 'Steve Jobs'
  console.log(founder) // 'Steve Jobs'
}
console.log(founder) // Error not defined

var / let : règles de portée (scope)

Règles de portée (ou "scope")
var = portée des fonctions
let = portée de blocs (if, for...)

var / let : règles de portées (scope)

// Anciennement var (ES5)
for (var i = 0; i <= 10; i++) {
  console.log(i) // 0 à 10
}
console.log(i) // 11


// Avec let (ES6)
for (let i = 0; i <= 10; i++) {
  console.log(i) // 0 à 10
}
console.log(i) // Error not defined

Règles de portée (ou "scope")
var = portée des fonctions
let = portée de blocs (if, for...)

// Camel case
const myAwesomeFoo = 'bar'

// Snake case
const my_awesome_foo = 'bar'

// Pascal case
const MyAwesomeFoo = 'bar'

// Kebab case
const my-awesome-foo = 'bar' // ⚠️ ERREUR

// D'autres conventions existent...

Nommer une variable

Les variables ne peuvent pas commencer par un chiffre

L'anglais est préférable

Le Pascal case est plus approprié pour les classes, moins pour les variables

Types de variables

String "Hello World"
Number 4
4.847
Boolean true
false
Array ["Hello", "World"]
Object { id: "Hello World" } 
Function () => { return 'Hello World' }
const foo = 'Hello'
const bar = ['Hello']

console.log(typeof(foo))
// Output: "string"

console.log(typeof(bar))
// Output: "object"

console.log(Array.isArray(bar))
// Output: true

D'autres types existent ; ceux présentés ci-dessus sont les plus courants

typeof n'est pas un outil fiable

Stocker et manipuler des données
avec un tableau / un objet

const foo = ['Hello']

foo.push('World')
// Create - ['Hello', 'World']

foo[1] = 'Man'
// Update - ['Hello', 'Man']

foo.splice(0, 1)
// Delete - ['Man']
const foo = { 
  title: 'Hello World',
  tagline: 'Awesome tagline'
}

// Create
foo.image = 'hello-world.jpg'

// Update
foo.title = 'Hello Man'

Opérations

Il existe plusieurs types d'opérateurs

Type Exemple
Opérateurs arithmétiques x + y, x / y
Opérateurs d'affectation x = y, x += y
Opérateurs de comparaison x === y, x >= y
Opérateurs logiques x && y, x || y
Opérateurs de chaînes de caractères 'Hello' + 'World'
Opérateur conditionnel ternaire x === y ? 'yes' : 'no'
Opérateurs unaires typeof(x)

D'autres types d'opérateurs existent, ceux présentés ci-dessus sont les plus courants

L'objet Math

Math.abs(-4.8)
// 4.8

Math.floor(4.8)
// 4

Math.ceil (4.8)
// 5

Math.round(4.8)
// 5

Math.random()
// 0.7628140805056463
// Entre 0 et 1

Math est un objet natif de JavaScript

Bien d'autres opérations peuvent être effectuées, celles présentées ci-contre sont les plus courantes

Concaténation

const year = '2021'

// ES5
const bar = 'La P' + year + 'est au top'

// ES6
const foo = `La P${year} est au top`
const foo = `La P${2000 + 21} est au top`

// La P2021 est au top

En ES6, on englobe les variables dans des "backticks" ; cette méthode est appelée "littéraux de gabarit"

Conditions

if / else if / else

const foo = 2017
let output

if (foo < 2021) {
  output = 'if'
} else if (foo === 2017) {
  output = 'else if'
} else {
  output ='else'
}
console.log(output) // 'if'

Dès qu'une condition est valable elle est appliquée ; les conditions suivantes ne sont plus vérifiées

On peut vérifier des nombres avec
<   <=   >=   >   ==   ===

switch

const foo = 2015
let output

switch (foo) {
  case 2017:
    output = 'Hello 2017'
    break
  case 2016:
  case 2015:
    output = 'Hello 2015 / 2016'
    break
  default:
    output ='default'
}

console.log(output) // 'Hello 2015 / 2016'

L'instruction break permet de sortir du switch si une condition est validée

Dans certains cas switch peut être utile, mais il est préférable d'utiliser if avec else if

Différence entre == et ===

const foo = '2017'

let output
if (foo == 2017) {
  output = 'if'
} else {
  output = 'else'
}
console.log(output) // 'if'

let output
if (foo === 2017) {
  output = 'if'
} else {
  output = 'else'
}
console.log(output) // 'else'

== valeur
=== valeur + type

Vérifier un booléen

const foo = true
const bar = false


// Au lieu de :
if (foo === true) { ... }
 
// On peut faire :
if (foo) { ... }


// Au lieu de :
if (bar === false) { ... }

// On peut faire :
if (!bar) { ... }

Vérifier plusieurs conditions en une seule

const foo = 'Hello'
const bar = 2017

if (foo === 'Hello' && (bar <= 2000 || bar === 2017)) {
  console.log('ok')
} else {
  console.log('fail')
}

// 'ok'
&& et
|| ou

Boucles

for

for (let i = 0; i <= 10; i++) {
  console.log(i) // 0 à 10
}
for (let i = 10; i >= 0; i--) {
  console.log(i) // 10 à 0
}
for (let i = 0; i <= 10; i += 5) {
  console.log(i) // 0, 5, 10
}
let i = 0 Initialisation
i <= 10 Condition
i++ Incrémentation
i-- Décrémentation
console.log(i) Instruction

Exemple : boucler sur un tableau

const foo = [
  { title: 'Hello' },
  { title: 'World' }
]

for (let i = 0; i < foo.length; i++) {
  console.log(foo[i].title) // 'Hello', 'World'
}

while

let year = 2000

while (year <= 2017) {
  console.log(year)
  year++
}

Il est préférable d'utiliser
​for au lieu de while

Fonctions

Déclarer une fonction

// Function declaration
function myFunction (x, y) {
  return x + y
}


// Function expression
const myFunction = function (x, y) {
  return x + y
}


// Function expression - Arrow function (Fonctions fléchées, ES6)
const myFunction = (x, y) => {
  return x + y
}
x, y Paramètres

return

const addition = function (x, y) {
  return x + y
  console.log('Not display')
}

const sum = addition(10, 5)
console.log(sum) // 15

return renvoie un résultat


Tout ce qui se trouve après return est ignoré

Fonctions fléchées : règles de portée (scope)

let obj = {
  bar: () => {
    return this
  }
}

console.log(obj.bar()) // window 
let obj = {
  bar: function () {
    return this
  }
}

console.log(obj.bar()) // obj

Le "this" d'une fonction fléchée n'est pas le même que le "this" d'une fonction "classique"

Interaction avec le DOM

Récupérer des éléments du DOM

document.getElementById('foo')
document.getElementsByClassName('foo')
document.getElementsByTagName('header')

document.querySelector('#foo')
document.querySelectorAll('.foo')
document.querySelectorAll('header')

Modifier les attributs d'un élément

const foo = document.querySelector('#foo')

foo.setAttribute('data-value', 'bar')
foo.getAttribute('data-value')
foo.removeAttribute('data-value')

Modifier le style d'un élément

const foo = document.querySelector('#foo')

foo.style.color('#FF0000')
foo.style.backgroundColor('#000')
foo.style.width = '100px'

Les propriétés de style sont écrites en camelCase

Modifier les classes d'un élément

const foo = document.querySelector('#foo')

foo.classList.add('foo')
foo.classList.add('foo', 'bar')
foo.classList.remove('foo')
foo.classList.contains('foo')

Modifier le contenu d'un élément

const foo = document.querySelector('#foo')

foo.innerText = 'bar'
foo.inneHTML = '<span>bar</span>'

Créer / Ajouter / Supprimer un élément

// Créer un élément span et lui appliquer un id
const foo = document.createElement('span')
foo.id = 'bar'

// Ajouter cet element dans le DOM, au sein et à la fin de #main-header
document.querySelector('#main-header').appendChild(foo)

// Supprimer cet élément
document.querySelector('#bar').remove()

Événements

Écouter un événement

// Récupérer un élément du DOM
const foo = document.querySelector('#foo')

// Écouter l'événement "click"
foo.onclick = (event) => {
  // Callback
  console.log('click', event)
}

// Écouter l'événement "onmouseenter"
foo.onmouseenter = (event) => {
  console.log('mouse enter', event)
}

Le paramètre "event" est un objet renvoyé nativement lorsque un événement se produit 

preventDefault

// Récupérer un élément du DOM
const foo = document.querySelector('input[type="checkbox"]')

// Écouter l'événement "click"
foo.onclick = (event) => {
  console.log('click', event)
  event.preventDefault()
}

"preventDefault" est une des méthodes contenues dans "event"

Appelée dans le callback, elle permet  d'annuler le comportement natif d'un élément

addEventListener

const foo = document.querySelector('#foo')
const bar = document.querySelector('#bar')

// click : on peut écouter un seul événement click
foo.onclick = (event) => {
  console.log('click', event)
}

// addEventListener : on peut écouter 2 événements click 
bar.addEventListener('click', (event) => {
  console.log('click 2', event)
})
bar.addEventListener('click', (event) => {
  console.log('click 1', event)
})

La méthode "addEventListener" permet d'écouter plusieurs fois un même type d'événement sur un même élément

removeEventListener

const foo = document.querySelector('#foo')

// Callback function
const callbackClick = () => {
  console.log('click')
}

// addEventListener
foo.addEventListener('click', callbackClick)

// removeEventListener
foo.removeEventListener('click', callbackClick)

La méthode "removeEventListener" permet de retirer l'écoute d'un événement définie par "addEventListener"

L'objet window

window

L'objet "window" contient des informations intéressantes, notamment :

history Historique de navigation
localStorage Stockage de données
location Données sur l'url d'une page
navigator Données sur le navigateur
screen Données sur l'écran
scrollX, scrollY Valeurs du scroll horizontal / vertical
innerWidth, innerHeight Taille de la fenêtre

window

Quelques méthodes intéressantes :

alert / prompt Afficher une modal
focus / blur Focus / blur sur un input / un select
setTimeout / setInterval Exécuter des instructions après un  certain délai
scrollTo Scroller à une certaine valeur
open Ouvrir une nouvelle fenêtre / tab du navigateur

setTimeout

// Afficher une modal après 3 sec.

setTimeout(() => {
  alert('Hello Modal')
}, 3000)

Workflow JavaScript
Modules et composants web

Package managers

Gestion des librairies / plugins via un

gestionnaire de paquets 

Package managers populaires

 

npm

 

Yarn

// package.json
{
  "name": "my-portfolio-package",
  "version": "1.0.0",
  "dependencies": {
    "jquery": "^2.2.3"
  }
}

Yarn

// Commande pour installer le package jquery par exemple :
yarn add jquery

Linters JavaScript

Outil pour garder un code JS lisible, cohérent et harmonieux

Plugins

Modules et composants

C'est quoi ? Pourquoi ?

Un site / application web

doit être le plus

maintenable possible

💪

Programmation modulaire

 Consiste à utiliser une

approche modulaire de l'architecture d'un projet informatique

Module Javascript

Concept appliqué au

Javascript

Composant web

Plus large qu'un module :

Template HTML + Javascript + Style CSS

Systèmes de modules

Différents systèmes pour créer des modules Javascript

Plusieurs systèmes pour créer des modules Javascript

 

AMD


CommonJS 


ES2015 Modules

// operators.js

define([], function () {
  return {
    sum: function (a, b) {
      return a + b
    },
    divide: function (a, b) {
      return a / b
    }
  }
})
// app.js

define(["./operators.js"], function (operators) {
  var test = operators.sum(10, 5) // 15
})

AMD

Asynchronous Module Definition

// operators.js

exports.sum = function (a, b) {
  return a + b
}

exports.divide = function (a, b) {
  return a / b
}
// app.js

var operators = require('./operators.js')

var test = operators.sum(10, 5) // 15

CommonJS

// operators.js

const myObject = {}

myObject.sum = (a, b) => {
  return a + b
}

myObject.divide = (a, b) => {
  return a / b
}

export default myObject
// app.js

import operators from './operators.js'

const test = operators.sum(10, 5) // 15

ES2015 Modules

Module bundlers

Un outil qui analyse les modules pour générer des assets

Module bundlers populaires

 

Browserify


Webpack

Webpack

Grafikart - Lien du tutoriel

module.exports = {

  // Points d'entrée
  entry: './assets/js/main.js',

  // Configuration de l'export
  output: {
    path: './build/js',
    filename: "main.js"
  },
  
  // Configuration des loaders
  module: {
    rules: [
      { test: /\.css$/, loader: "style-loader!css-loader" },
    ]
  },
  
  // Configuration des plugins
  plugins: []
	
}

Webpack

Frameworks JavaScript
Introduction à Vue.js

Frameworks JavaScript

Un outil tout en un pour créer une application maintenable

Frameworks JS populaires

2010

2011

2011

2013

 

2009

2013

2014

Jeremy Ashkenas

Yehuda Katz

Meteor

Google

 

Google

Facebook

Evan You

Facile à prendre en main

Développement rapide

Un écosystème flexible grâce aux différents plugins Vue

Mises à jour régulières

Communauté active

JavaScript - WSF 2e année

By Vincent Garreau

JavaScript - WSF 2e année

Initiation au JavaScript

  • 878