Pár tipů na psaní projektových javascriptů
April 20, 2017
Javascripty jsou jedna z největších bolestí při vývoji webových stránek. Občas se člověk neudrží a s odstupen času by si radši prostřelil nohu, než aby hledal bug v napsaném skriptu.
Od verze 2.6 je připravená výchozí struktura souboru init-app.js pro projekty. Defaultní podobu najdete v cdn/template_core/js/init-app.js. Sjednocená struktura nám umožní přehledně upravovat vše v jednom souboru.
Základní rozdělení skriptů je popsáno v draftu JS styleguidu. Pro rychlou představu je hierarchie zobrazena na obrázku níže.
Na každé úrovni je přetížena metoda init: function(){...}, která inicializuje veškeré skripty na webu. Soubor init-app.js není povinný, tzn. pokud nejsou v projektu žádné custom skripty, vůbec v repositáři není.
Tip č.1: Rozšiřujte již existující objekt App
Objekt App je globální JS a inicializuje všechny společné javascripty. Proto je dobré ho použít jako výchozí bod i pro rozšiřování custom skriptů na projektu. V template_core/js/init-app.js je jeho základní podoba včetně komentářů, zjednodušeně vypadá asi takto:
(function($, App, window, undefined) { 'use strict';
var App = window.App = $.extend(true, {}, App, {
init: function (config) {
this.config = config;
this.initCore(config);
this.initTemplate();
// your code
}
});
});
Tip č.3: Oddělujte kód do funkcí
Každá specifická funkce by měla být oddělená, ve chvíli, kdy je JS jedna dlouhá nekončící nudle, se zpětně velmi těžko cokoli dohledává. Proto chceme funcionalitu separovat a izolovat. Je to krok k více modulárnímu kódu i na úrovni projektu.
Příklad klasického kódu
$(document).ready(function() {
$(".js-play-video").fancybox({
type:"iframe",
fitToView:true,
width:"80%",
height:"90%",
autoSize:false,
closeClick:false,
openEffect:"fade",
closeEffect:"fade",
helpers : {
overlay : {
css : {
'background' : 'black'
}
}
}
});Příklad oddělení jednotlivých funkcí
/*
* Initialize only project specific functions
*/
initProject: function (){
var that = this;
$(document).ready(function() {
that.runPlayVideoLinks();
});
},
// Function opens link with .js-play-video class in fancybox
runPlayVideoLinks: function (){
$(".js-play-video").fancybox({
type:"iframe",
fitToView:true,
width:"80%",
height:"90%",
autoSize:false,
closeClick:false,
openEffect:"fade",
closeEffect:"fade",
helpers : {
overlay : {
css : {
'background' : 'black'
}
}
}
});
},
Tip č.3: Definujte event handlery zvlášť
Toto je spíš kosmetická záležitost, ale obvykle je lepší nepsat event handlery jako anonymní funkce. Kód je přehlednější, dá se lépe debuggovat, refaktorovat a rozšiřovat. Lze pak třeba i event listener odebrat přes funkci off().
Příklad klasického kódu
var $table_trigger = $('.js-table-trigger');
$table_trigger.click(function (e) {
e.preventDefault();
$(this).toggleClass("arrow-open");
$(this).closest("tr").next().toggle();
});
Příklad handleru jako samostatné funkce
var $table_trigger = $('.js-table-trigger');
var handleTableTriggerClick = function(e){
e.preventDefault();
$(this).toggleClass("arrow-open");
$(this).parent().toggle();
}
// Handle table trigger collapsing
$table_trigger.on('click', handleTableTriggerClick);
Tip č.4: Nepoužívejte show() a hide()
Připravené funkce od jQuery jsou pomalé. Obecně je za good practice považováno, pokud chcete nějaký prvek schovat nebo zobrazit, používat třídy. V solidpixels na to máme třídy:
- show - zobrazí prvek jako display:block
- hide - schová prvek (s !important)
Tip č.5: Ošetřete výkonově problematické eventy
V JS máme typicky několik problematických eventů, které mohou způsobit problémy, když se špatně použijí. Jsou to hlavně: scroll a resize. Tyto eventy by měly být na webu vždy ošetřené. Slouží k tomu funkce $.throttle a $.debounce, které máme v core utilities. Jejich podrobný popis naleznete v článku Debouncing and Throttling Explained Through Examples.
Následující funkce se volá při každém resizu, což znamená změna o 1px. Pokud okno táhnu o 350px, tak se zavolá 350krát.
$(window).on('resize', handleResize);Ošetřená varianta se zavolá maximálně jednou za 50ms, což je z hlediska uživatele málo postřehnutelné, ale pro výkon browseru to má velký dopad.
$(window).on('resize', $.throttle(handleResize, 50));