Warsztaty JavaScript
JavaScript Developer @ Evojam
@RobertDuraj
rduraj@gmail.com
Robert Duraj
http://bit.ly/js-lingua-franca
Cel: Facebook 2.0
- Teoria vs Praktyka
- Iteracyjne zdobywanie wiedzy
- Ciągły refactoring
- Prosto do działającego projektu!
Agenda
- Sekcja #1:
- API (server, przeglądarka)
- Środowisko testowe (projekt startowy)
- Twoje pierwsze "Hello World"
- QnA
- TODO
Agenda
- Sekcja #2:
- Idea komponentu (CDD)
- zmienne, stałe
- funkcje
- QnA
- TODO
Agenda
- Sekcja #3:
- instrukcje warunkowe
- obiekty i tablice
- pętle
- QnA
- TODO
Agenda
- Sekcja #4:
- zdarzenia
- nasłuchiwanie na zdarzenia
- QnA
- TODO
Agenda
- Sekcja #5:
- EcmaScript 5 - 2018
- QnA
- TODO
Agenda
- Sekcja #6:
- LocalStorage
- SessionStorage
- Cookies
- QnA
- TODO
Agenda
- Sekcja #7:
- Komunikacja z API aplikacji
- Callbacks
- Promises
- QnA
- TODO
Agenda
- Sekcja #8:
- Konteksty
- Prototypy
- QnA
- TODO
Sekcja #1
API
Application Programming Interface
- przeglądarki
- aplikacji
- klasy
- urządzenia
- etc.
Projekt startowy:
- http://bit.ly/js-workshop-template
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="./styles/app.css" />
</head>
<body>
<header>
<h1>My FB</h1>
</header>
<main>
<p>FB content</p>
</main>
<footer>© JS workshops 2018</footer>
</body>
</html>
Jak zacząć pracę z JS?
Jak zacząć pracę z JS?
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="./styles/app.css" />
</head>
<body>
<header>
<h1>My FB</h1>
</header>
<main>
<p>FB content</p>
</main>
<footer>© JS workshops 2018</footer>
<script src="./scripts/app.js" />
</body>
</html>
<script src="./scripts/app.js" />
<script>
// JS code here
</script>
Praca z API Twojej przeglądarki
// ./scripts/app.js
window.alert("Hello Bielsko!")
// ./scripts/app.js
console.log(window);
Dev tools API
// ./scripts/app.js
window.console.log(window);
QnA
TODO:
- Stwórz w projekcie plik ./scripts/app.js
- Załaduj w index.html, przed zakończeniem taga <body> skrypt JS: ./scripts/app.js
- Napisz prosty skrypt (w dołączonym wcześniej pliku), wyświetlający Twoje imię w przeglądarce, korzystając z metody alert(...)
- Zamień metodę alert() na prompt() i zobacz, czym różnią się obie te metody.
Sekcja #2
CDD
Component
Driven
Development
HTML-based templates
<div class="card">
<h5><time>17.05.2018</time> - Bob Dylan</h5>
<p>Knockin' On Heaven's Door...</p>
</div>
<script type="text/template" id="message-template">
<div class="card">
<h5><time>{{date}}</time> - {{author}}</h5>
<p>{{message}}</p>
</div>
</script>
<script type="text/template" id="message-template">
<div class="card">
<h5><time>17.05.2018</time> - Bob Dylan</h5>
<p>Knockin' On Heaven's Door...</p>
</div>
</script>
Jak pracować z szablonem?
// ./scripts/app.js
window.document.getElementById('message-template');
// ./scripts/app.js
console.log(window.document.getElementById('message-template').innerHTML);
Przypisanie do zmiennej
// ./scripts/app.js
const templateElement = window.document.getElementById('message-template');
console.log(templateElement.innerHTML);
// ./scripts/app.js
const getTemplateById = window.document.getElementById;
console.log(getTemplateById('message-template').innerHTML);
Operatory przypisania i typy
// ./scripts/app.js
let A = 'jakiś string';
//...
A = 4;
console.log(A); // 4
// ./scripts/app.js
const A = 'jakiś string';
const B = ' z dopiskiem';
const C = 5;
console.log(A + B); // 'jakiś string z dopiskiem';
console.log(A + B + C); // 'jakiś string z dopiskiem5';
Operatory przypisania i typy
// ./scripts/app.js
let A = 'Hello ';
A += 'World'; // A = A + 'World';
// ./scripts/app.js
const A = 'jakiś string';
const B = ' z dopiskiem';
console.log(B - A); // NaN
const C = '2';
const D = '1';
console.log(C - D); // 1
Tworzenie funkcji - function, return
// ./scripts/app.js
const templateElement = window.document.getElementById('message-template');
console.log(templateElement.innerHTML);
// ./scripts/app.js
function getTemplateByName(name) {
var templateId = name + '-template';
var templateElement = window.document.getElementById(templateId);
return templateElement.innerHTML;
}
const template = getTemplateByName('message');
// ./scripts/app.js
const getTemplateByName = function(name) {
return window.document.getElementById(name + '-template').innerHTML;
}
const template = getTemplateByName('message');
Czym jest zasięg widoczności zmiennej?
const A = 'stała o zasięgu globalnym';
function test() {
console.log(A); // stała o zasięgu globalnym
const B = 'stała o zasięgu funkcji';
var C = 'zmienna var o zasięgu funkcji';
if (true === true) {
console.log(A); // stała o zasięgu globalnym
console.log(B); // stała o zasięgu funkcji
console.log(C); // 'zmienna var o zasięgu funkcji'
let D = 'zmienna let o zasięgu klamry';
}
console.log(B); // stała o zasięgu funkcji
console.log(C); // 'zmienna var o zasięgu funkcji'
console.log(D); // udefined
}
test();
console.log(A); // stała o zasięgu globalnym
console.log(B); // udefined
console.log(C); // udefined
console.log(D); // udefined
var, let, const - zatem kiedy?!
CONST
QnA
TODO:
- Stwórz template dla pojedynczej wiadomości w pliku index.html
- W pliku ./scripts/app.js stwórz metodę getTemplateByName do pobierania template'ów po nazwie, przetestuj na szablonie wiadomości z #1
- Skorzystaj z utworzonej funkcji getTemplateByName i dodaj pobrany szablon do obiektu #list korzystając z metod getElementById i właściwości innerHTML
Sekcja #3
Instrukcje warunkowe - If, else, switch
// ./scripts/app.js
if (...warunek) {
// then
} else {
// then
}
// ./scripts/app.js
if ('5' === 5) {
console.log('A')
} else {
console.log('B');
}
// ./scripts/app.js
switch (letter) {
case 'A':
console.log('A jak Ala!');
break;
case 'B':
console.log('B jak BMW!');
break;
default:
console.log('Każda inna litera też jest fajna!');
}
Obiekty i tablice
Obiekty
// ./scripts/app.js
const dog = {
name: 'Frodo',
bark: function () {
console.log('woof! woof!');
}
};
console.log(dog); // { name: 'Frodo', bark: f }
console.log(dog.name); // Frodo
console.log(dog.bark()); // woof! woof!
// ./scripts/app.js
const oldHello = "Hello World";
const betterHello = oldHello.replace('World', 'Bielsko');
console.log(oldHello); // "Hello World"
console.log(betterHello); // "Hello Bielsko"
Tablice
// ./scripts/app.js
const messages = [];
// ./scripts/app.js
const messages = [];
console.log(typeof messages); // "object"
// ./scripts/app.js
const messages = [1, 2, 3, 4];
messages.push(5);
console.log(messages); // [1, 2, 3, 4, 5];
messages.pop();
console.log(messages); // [1, 2, 3, 4];
messages.shift();
console.log(messages); // [2, 3, 4];
Pętle
// ./scripts/app.js
const messages = [
{ name: 'Bob Dylan', message: 'Like a Rolling Stone...' },
{ name: 'Batman', message: 'I am Batman!' },
];
// ./scripts/app.js
for (let index = 0; index < messages.length; index++) {
console.log(messages[index]); // { name: ..., message: ... };
}
// ./scripts/app.js
messages.forEach(function(message) {
console.log(message); // { name: ..., message: ... };
});
TODO:
Z podanej tablicy quotes, za pomocą pętli, stwórz listę bohaterów Władcy Pierścieni, pomijając osoby, które nie wystąpiły w książce...
const quotes = [
{
name: 'Lady Galadriel',
quote: 'Even the smallest person can change the course of history.',
},
{
name: 'Frodo',
quote: 'It is useless to meet revenge with revenge: it will heal nothing.',
},
{
name: 'Yoda',
quote: 'Do or do not. There is no try',
},
]
map & filter
// ./scripts/app.js
const messages = [
{ name: 'Bob Dylan', message: 'Like a Rolling Stone...' },
{ name: 'Batman', message: 'I am Batman!' },
];
// ./scripts/app.js
const authors = messages.map(function(message) {
return message.name;
});
console.log(authors); // ['Bob Dylan', 'Batman'];
// ./scripts/app.js
const batmanMessages = messages.filter(function(message) {
return message.name === 'Batman';
});
console.log(batmanMessages); // [{ name: 'Batman', message: 'I am Batman!' }];
TODO:
Zamień poprzednio utworzoną pętlę na połączone metody filter i map, wykonując to samo zadanie:
const quotes = [
{
name: 'Lady Galadriel',
quote: 'Even the smallest person can change the course of history.',
},
{
name: 'Frodo',
quote: 'It is useless to meet revenge with revenge: it will heal nothing.',
},
{
name: 'Yoda',
quote: 'Do or do not. There is no try',
},
]
reduce
const numbers = [1, 2, 3, 5, 7, 3];
numbers.reduce(function(accumulate, current) {
return accumulate + current;
}, 0);
// 21
const messages = [
{ name: 'Bob Dylan', message: 'Like a Rolling Stone...' },
{ name: 'Batman', message: 'I am Batman!' },
];
messages.reduce(function(acc, cur) {
return acc + cur.name + ' ';
}, '');
messages
.map(function(message) {
return message.name;
})
.join(', ');
QnA
TODO:
- Stwórz tablicę messages
- Dodaj do niej dwa obiekty, zawierające pola name oraz message
- Stwórz metodę createMessage, która będzie oczekiwać dwóch argumentów: name i message
- W metodzie createMessage pobierz szblon wcześniej utworzoną metodą (getTemplateByName) i korzystastając z metody (String).replace, zamień {{name}} i {{message}} na argumenty funkcji (name i message)
TODO:
- Zmapuj tablicę messages, tak, żeby zawierała szablony wiadomości stworzone przez createMessage
- Dodaj każdy kolejny element zmapowanej tablicy messages do obiektu #list wyświetlając wszystkie elementy na widoku.
Powtórka
Zmienne, stałe
const A = 'stała A'
const numberA = 5
let B = 'zmienna B'
let numberB = 5
console.log(A) // 'stała A'
console.log(numberA) // 5
console.log(B) // 'zmienna A'
console.log(numberB) // 5
B = 'zmienna zmieniona B'
console.log(B) // 'zmienna zmieniona B'
Operatory arytmetyczne
console.log(5+5); // 10
const A = 5;
const B = 5;
console.log(A+B) // 10
console.log(A-B) // 0
console.log(A/B) // 1
console.log(A*B) // 25
console.log(A%B) // 0
const stringA = 'Ala ma ';
const stringB = 'kota';
console.log(stringA + stringB); // 'Ala ma kota'
Funkcje
function nazwaFunkcji (argument1, argument2, argument3) {
console.log(argument1, argument2, argument3);
}
nazwaFunkcji('A', 'B', 5); // 'A' 'B' 5
Obiekty
const jedi = {
imie: 'Yoda',
usePower: function () {
console.log('Mmmm, do or do not, there is no try');
}
}
function Jedi () {
this.imie = 'Yoda';
this.useForce = function () {
console.log('Mmm. Do or do not, there is no try');
}
}
const Yoda = new Jedi();
Yoda.useForce();
Tablice
const tablica = [];
tablica.push('A');
console.log(tablica); // ['A'];
tablica.push('B');
tablica.shift();
console.log(tablica) // ['B']
Pętla forEach
const tablica = ['Ala', 'ma', 'kota']
tablica.forEach(function(slowo) {
console.log(slowo.toUpperCase());
}) // 'ALA' 'MA' 'KOTA'
http://bit.ly/js-workshop-template-2
Sekcja #4
Zdarzenia w DOM
Zdarzenie kliknięcia
<button onClick="alert('Hello World');">Przywitaj się!</button>
// ./scripts/app.js
document.getElementById('hello-button').addEventListener('click', function() {
alert('Hello World!');
});
<button id="hello-button">Przywitaj się!</button>
Popularne eventy:
- onChange
- onClick
- onMouseOver
- onMouseOut
- onKeyDown
- onLoad
- focus
- blur
QnA
TODO:
- Dodaj ID do przycisku wyślij w formularzu wiadomości
- Przechwyć za pomocą listenera moment kliknięcia w button
- Pobierz wartość pola textarea za pomocą wartości .value na elemencie textarea i zapisz ją do zmiennej
- Utwórz wiadomość za pomocą createMessage i dodaj ją do listy.
Sekcja #5
Arrow functions
() => {}
/*
function() {}
*/
value => value
/*
function(value) { return value; }
*/
() => ({ field: 'value' })
/*
function() {
return {
field: 'value',
}
}
*/
const getTemplateByName = name => window
.document
.getElementById(name + '-template')
.innerHTML;
Destructuring objects
function logUser(user) {
console.log(user.firstName, user.lastName, user.email);
}
function logUser({ firstName, lastName, email }) {
console.log(firstName, lastName, email);
}
function logArray(array) {
console.log(array[0], array[1]);
}
logArray(['firstElement', 'secondElement']); // 'firstElement', 'secondElement'
function logArray([firstElement, secondElement]) {
console.log(firstElement, secondElement);
}
logArray(['firstElement', 'secondElement']); // 'firstElement', 'secondElement'
Spread operator / rest parameters (...)
function logArguments() {
console.log(arguments);
}
logArguments('A', 'B', 'C'); // Arguments: ['A', 'B', 'C']
function logArguments(firstArgument, ...rest) {
console.log(firstArgument, rest);
}
logArguments('A', 'B', 'C'); // Arguments: 'A', ['B', 'C']
class
class A {
constructor() {
this.AField = 'A';
}
showA() {
console.log(this.AField);
}
}
class B extends A {
constructor() {
super()
this.BField = 'B';
}
showAB() {
console.log(this.AField, this.BField);
}
}
const AB = new B();
AB.showAB();
Default function parameters
function showMessage(message, author) {
if (author === undefined) {
author = 'Anonymous';
}
return '"'message + '" by ' + author;
}
function showMessage(message, author = 'Anonymous') {
return '"'message + '" by ' + author;
}
Template Literals
const owner = 'Ala';
const oldFashionTemplate = 'Mała ' + owner + ' ma kota';
const withTemplateLiterals = `Mała ${owner} ma kota`;
function showMessage(message, author = 'Anonymous') {
return `"${message}" by ${author}`;
}
QnA
TODO:
- Zrefaktoryzuj dotychczasowy kod, korzystając z możliwości jakie oferuje nowa specyfikacja EcmaScript
- Postaraj się wykorzystać jak najwięcej nowych elementów
- Wykorzystaj np. arrow functions do skrócenia zapisu .map
Sekcja #6
Dostęp do localStorage
window.localStorage.setItem('key', value);
window.localStorage.getItem('key');
window.localStorage.removeItem('key');
Obiekty w localStorage
window.localStorage.setItem(
'messages',
JSON.stringify([{ message: 'text', author: 'Bob Dylan']),
);
const messages = JSON.parse(localStorage.getItem('messages'));
Dostęp do sessionStorage
window.sessionStorage.setItem('key', value);
window.sessionStorage.getItem('key');
window.sessionStorage.removeItem('key');
Dostęp do cookies
document.cookie = "yummy_cookie=choco";
document.cookie = "tasty_cookie=strawberry";
console.log(document.cookie);
// logs "yummy_cookie=choco; tasty_cookie=strawberry"
const d = new Date();
d.setTime(d.getTime() + 5*1000); // in milliseconds
document.cookie = 'foo=bar;path=/;expires='+d.toGMTString()+';';
QnA
TODO:
- Zapisz każdą nową dodaną wiadomość do localStorage
- Po załadowaniu skryptu, odczytaj wszystkie wiadomości z localStorage i wyświetl na stronie
Sekcja #7
TBC
Sekcja #8
TBC
JS Workshops
By Robert
JS Workshops
- 287