Příručka:Kódovací konvence/JavaScript
Tato stránka dokumentuje pokyny pro vývoj MediaWiki, vytvořené v průběhu času na základě dohovoru vývojářů (nebo někdy na základě prohlášení hlavního vývojáře) |
Tato stránka popisuje kódovací konvence pro JavaScript v kódová základně MediaWiki. Viz také obecné konvence.
Odkazování
Jako náš nástroj pro kvalitu kódu používáme ESLint s přednastavením eslint-config-wikimedia pro kódování většiny našich stylů kódování a pravidel kvality kódu. Na stránce Integrations na eslint.org najdete mnoho textových editorů nebo IDE s pluginy, které poskytují živou zpětnou vazbu při psaní.
Konfigurace Linter
Chcete-li z analýzy vyloučit soubory nebo adresáře (např. knihovny třetích stran), můžete konfigurovat vzory ignorování v ESLint prostřednictvím souboru .eslintignore
.[1]
Všimněte si, že node_modules
je ve výchozím nastavení vyloučen, takže většina repozitářů nemusí nastavovat žádná pravidla ignorování.
Každé repo potřebuje soubor .eslintrc.json
v kořenovém adresáři úložiště.
Následuje příklad konfiguračního souboru ESLint:
{
"root": true,
"extends": [
"wikimedia/client",
"wikimedia/jquery",
"wikimedia/mediawiki"
],
"globals": {
// Celoprojektové globální.
},
"rules": {
// Variace pravidel pro celý projekt. Omezte na minimum.
}
}
Živé příklady viz .eslintrc.json v MediaWiki a VisualEditoru.
Nezapomeňte nastavit "root": true
, abyste předešli nechtěnému "magickému dědění" konfigurací ESLint v nesouvisejících nadřazených adresářích, které jste vy nebo server CI mohli nastavit na disku (například mezi rozšířením MediaWiki a jádrem MediaWiki nebo mezi vaším projektovým adresářem a něčím v váš domovský adresář).
Přednastavení eslint-config-wikimedia poskytuje několik profilů, ze kterých si mohou projekty vybrat, jak uznají za vhodné, jako jsou různé jazykové příchutě nebo globální prostředí běhového prostředí. Například:
wikimedia/client
- pro kód prohlížeče v aktuálním výchozím prostředí ES (aktuálně ES6, tedy aliaswikimedia/client-es6
)wikimedia/client-es5
- pro kód prohlížeče očekává podporu ES5wikimedia/client-es6
- pro kód prohlížeče, který očekává podporu ES6
wikimedia/server
- pro kód Node.js 10+ a očekává podporu ES2018wikimedia/qunit
- mix pro testy QUnit
Měli byste očekávat použití více souborů .eslintrc.json
v repo pro nastavení různých environmentálních očekávání pro různé podadresáře.
Tím je zajištěno, že nepoužijete náhodou metody window
v kódu serveru, který očekáváte na serveru, nebo že v produkčním kódu neodkážete na QUnit.
.eslintrc.json
soubory v podadresářích automaticky dědí z konfigurace nadřazeného adresáře, takže musí obsahovat pouze věci, které jsou specifické pro daný adresář (example file).
Průběžná integrace
Projektům se doporučuje, aby prosadily předávání ESLint tím, že do něj zahrnou svůj npm test
skript pomocí příkazu "test" do package.json
.
Více informací o tom najdete na Continuous integration/Entry points.
Pokud má váš projekt poměrně náročný testovací kanál, lze definovat skript npm run lint
nebo dokonce npm run lint:js
v package.json
, aby bylo snadné spouštět pouze ty z příkazového řádku během místního vývoje (abyste nemuseli otevírat každý soubor v editoru a/nebo čekat na CI).
Chcete-li odhalit další funkce příkazového řádku z ESLint (jako je lintování jednotlivých souborů mimo textový editor nebo použití funkce --fix), definujte "eslint" jako vlastní skript v package.json bez jakéhokoli argumentu. Poté jej můžete vyvolat z příkazového řádku následovně:
# Celý adresář, rekurzivní
$ npm run eslint -- .
$ npm run eslint -- resources/
# Jeden soubor
$ npm run eslint -- resources/ext.foo/bar.js
# Ustálený
$ npm run eslint -- --fix resources/ext.foo/
Prázdné místo
Mezery
Používáme následující konvence:
- Odsazení s tabulátory.
- Žádné mezery na konci.
- Oddělení jednoho bloku logicky souvisejícího kódu od druhého pomocí prázdných řádků.
- Jedna mezera na obou stranách binárních operátorů a operátorů přiřazení.
- Klíčová slova následovaná "
(
" (levá závorka) musí být oddělena jednou mezerou. To poskytuje vizuální rozlišení mezi klíčovými slovy a vyvoláním funkcí. - Mezi názvem funkce a levou závorkou seznamu argumentů by neměla být žádná mezera.
- Uvnitř závorek (jako jsou příkazy if, volání funkcí a seznamy argumentů) by měla být jedna mezera.
- Nepoužívejte operátory, jako by to byly funkce (například
delete
,void
,typeof
,new
,return
, ..).
Tyto a další aspekty našeho průvodce stylem jsou vynuceny pomocí ESLint.
Správně | Špatně |
---|---|
a.foo = bar + baz;
if ( foo ) {
foo.bar = doBar();
}
function foo() {
return bar;
}
foo = function () {
return 'bar';
};
foo = typeof bar;
function baz( foo, bar ) {
return 'gaz';
}
baz( 'banana', 'pear' );
foo = bar[ 0 ];
foo = bar[ baz ];
foo = [ bar, baz ];
|
a.foo=bar+baz;
if( foo ){
foo.bar = doBar () ;
}
function foo () {
return bar;
};
foo = function() {
return('bar');
};
foo = typeof( bar );
function baz(foo, bar) {
return 'gaz';
}
baz('banana', 'pear');
foo = bar[0];
foo = bar[baz];
foo = [bar,baz];
|
Délka řádku
Řádky by neměly být delší než 80–100 znaků. Pokud se příkaz nevejde na jeden řádek, rozdělte příkaz na více řádků. Pokračování prohlášení by mělo být odsazeno o jednu úroveň navíc.
Volání funkcí a objekty by měly být buď na jednom řádku, nebo rozděleny na více řádků s jedním řádkem pro každý segment. Vyvarujte se zavírání volání funkce nebo objektu v jiném odsazení, než je jeho otevření.
Ano |
---|
// Jeden řádek
if ( mw.foo.hasBar() && mw.foo.getThis() === 'that' ) {
return { first: 'Who', second: 'What' };
} else {
mw.foo( 'first', 'second' );
}
// Víceřádkový (jedna komponenta na řádek)
if (
// Oproti hlavičce odsazené o jednu úroveň.
mw.foo.hasBar() &&
mw.foo.getThis() === 'that' &&
!mw.foo.getThatFrom( 'this' )
) {
// ↖ Uzavírací závorka na stejné úrovni jako otevírání.
return {
first: 'Who',
second: 'What',
third: 'I don\'t know'
};
} else {
mw.foo(
[ 'first', 'nested', 'value' ],
'second'
);
}
|
Ne |
// Ne: Smíšené jednořádkové a víceřádkové
if ( mw.foo.hasBar() && mw.foo.getThis() === 'that' &&
!mw.foo.getThatFrom( 'this' ) ) {
// Ne: různý počet segmentů na řádek.
return { first: 'Who', second: 'What',
third: 'I don\'t know' };
} else {
mw.foo( 'first', 'second',
'third' );
// Ne: Výpisy vypadají, jako by byly rozděleny na více řádků, ale stále jsou v řádku.
// Visualy vypadá jako volání s jedním parametrem nebo s polem jako prvním parametrem.
mw.foo(
'first', 'second', 'third'
);
mw.foo(
[ 'first', 'nested', 'value' ], 'second'
);
}
|
Struktura
Ve zkratce:
// Proměnné, které mají doslovné a levné počáteční hodnoty
const baz = 42;
const quux = 'apple';
// Lokální funkce
function local( x ) {
return x * quux.length;
}
// Hlavní prohlášení
const foo = local( baz );
const bar = baz + foo;
Uzavření
Pokud balíček modulů nelze nebo z jiného důvodu ještě není registrován pomocí souborů balíčku , pak by jeho jednotlivé soubory JavaScriptu měly mít kolem kódu uzávěr na úrovni souboru.[2] To dává kódu jeho vlastní rozsah a zabraňuje úniku proměnných z nebo do jiných souborů, včetně režimu ladění, a způsobem, který je srozumitelný pro statickou analýzu. Tento vzor je známý jako ihned vyvolaný funkční výraz (nebo "iffy").[3]
U souborů balíčků to není potřeba, protože se spouštějí jako soubor "modul" spíše než soubor "script", který má přirozeně svůj vlastní lokální rozsah.
ESLint by měl být také nakonfigurován odpovídajícím způsobem (nastavte "parserOptions": { "sourceType": "commonjs" }
, jako v tomto příkladu).
Deklarování
Proměnné musí být deklarovány před použitím. Každé zadání musí být na samostatném řádku. Proměnné mohou být deklarovány blízko nebo při jejich prvním přiřazení.
const waldo = 42;
const quux = 'apple';
let foo, bar;
const flob = [ waldo ];
if ( isFound( waldo ) ) {
foo = 1;
bar = waldo * 2;
} else {
foo = 0;
bar = 0;
}
for ( let i = 0; i < flob.length; i++ ) {
// ...
}
Funkce by měly být deklarovány před použitím. V těle funkce by deklarace funkcí měly následovat po deklaracích proměnných a před jakýmikoli hlavními příkazy.
Komentáře
Komentáře by měly být na samostatném řádku a měly by být nad kódem, který popisují.
V rámci komentáře by měla být úvodní syntaxe (např. lomítko-lomítko nebo lomítko-hvězda) oddělena od textu jednou mezerou a text by měl začínat velkým písmenem. Pokud je komentář platnou větou, měla by být na jejím konci umístěna tečka.
Používejte řádkové komentáře (// foo
) ve funkcích a dalších blocích kódu (včetně víceřádkových komentářů).
Používejte blokové komentáře (/* foo */
) pouze pro bloky dokumentace.
To pomáhá udržovat konzistentní formátování vkládaných komentářů (např. ne některé jako bloky a některé jako víceřádkové komentáře nebo nutnost převádět z jednoho na druhý).
Vyhnete se také matoucím dokumentačním nástrojům.
Usnadňuje také deaktivaci částí kódu během vývoje pouhým posunutím zápisu koncového komentáře o několik řádků dolů, aniž by byl zkratován vloženým blokovým komentářem.
Buďte v komentářích liberální a nebojte se kvůli tomu velikosti souboru. Veškerý kód je před odesláním automaticky minimalizován o ResourceLoader .
Komentáře k dokumentaci
- Text v blocích volného tvaru by měl být velkými a malými písmeny (např. popis metod, parametrů, návratových hodnot atd.)
- Věty začínejte velkým písmenem.
- V popisu pokračujte na dalším řádku, odsazeném o jednu mezeru navíc.
/**
* Získejte uživatelské jméno.
*
* Vypracujte další odstavec po prvním jednořádkovém shrnutí
* imperativní nálada.
*
* @param {string} foo Popis parametru, který se nachází na
* dalším řádku komentáře.
* @param {number} bar
* @return {string} Uživatelské jméno
*/
Třídy ES5
Chcete-li zdokumentovat třídu, která používá syntaxi ES5 s třídou a konstruktorem definovanými společně jako function MyClass(…) {…}
, použijte:
- tag
@classdesc
pro dokumentování třídy - tag
@description
pro dokumentaci konstruktoru
/**
* @classdesc Popis třídy.
*
* @description Popis konstruktoru.
*
* @param {string} můj parametr
* @return {string} Popis
*/
Třídy ES6
Chcete-li zdokumentovat třídu, která používá syntaxi ES6 s konstruktorem definovaným pomocí constructor()
, použijte samostatné komentáře k dokumentaci třídy a konstruktoru.
/**
* Popis třídy.
*/
class myClass {
/**
* Popis konstruktoru.
*
* @param {string} můj parametr
* @return {string} Popis
*/
constructor() {...}
}
Vygenerovaná dokumentace
K vytvoření dokumentace použijte JSDoc (viz doc.wikimedia.org). Chcete-li nastavit a publikovat dokumentaci JSDoc, podívejte se na stránku JSDoc .
Rovnost
- Použijte operátory přísné rovnosti (
===
a!==
) místo (volné) rovnosti (==
a!=
). Ten druhý dělá typ nátlaku. - Nepoužívejte Yodovy podmínky.
Kontroly typů
- string:
typeof val === 'string'
- number:
typeof val === 'number'
- boolean:
typeof val === 'boolean'
- Function:
typeof val === 'function'
- object:
val === Object( val )
- plain object:
jQuery.isPlainObject( val )
- array:
Array.isArray( val )
- HTMLElement:
obj.nodeType === Node.ELEMENT_NODE
- null:
val === null
- undefined:
val === undefined
Řetězce
Pro řetězcové literály používejte jednoduché uvozovky místo dvojitých.
Pamatujte, že v JavaScriptu nejsou žádné "kouzelné uvozovky", tj. \n
a \t
fungují všude.
Chcete-li extrahovat část řetězce, použijte pro konzistenci metodu slice()
.
Vyhněte se metodám substr()
nebo substring()
, které jsou nadbytečné, snadno zaměnitelné a mohou mít neočekávané vedlejší účinky.[4][5][6]
Export
Použijte globální hodnoty vystavené prohlížečem (například document, location, navigator) přímo a ne jako vlastnosti objektu window.
To zvyšuje důvěru v kód prostřednictvím statické analýzy a může také umožňovat další funkce IDE.
Kromě globálů prohlížeče jsou bezpečné k použití pouze mw
, $
a OO
.
Vyhněte se vytváření nových globálních proměnných. Vyhněte se úpravám globálních prvků, které "nevlastní" váš kód. Například vestavěné globály, jako je String nebo Object, nesmí být rozšířeny o další obslužné metody a podobně by těmto globálům neměly být přiřazeny funkce související s OOjs nebo jQuery.
Chcete-li veřejně vystavit funkce pro opětovné použití, použijte module.exports
ze souborů balíčku anebo přiřaďte vlastnosti v rámci hierarchie mw
, např. mw.echo.Foo
.
Všimněte si, že konfigurační proměnné vystavené MediaWiki musí být přístupné přes mw.config
.
Prostředí
Úprava vestavěných prototypů, jako je Object.prototype
, je považována za škodlivou.
Toto není podporováno v kódu MediaWiki a pravděpodobně to povede k poškození nesouvisejících funkcí.
Pojmenovávání
Všechny proměnné musí být pojmenovány pomocí CamelCase začínající malým písmenem, nebo pokud proměnná představuje nějaký druh konstantní hodnoty, použijte velká písmena (s podtržítky pro oddělení).
Všechny funkce musí být pojmenovány pomocí CamelCase, obvykle začínající malým písmenem, pokud není funkce konstruktorem třídy, v takovém případě musí začínat velkým písmenem.
Funkce Metod jsou preferovány se začátečním slovesem, např. getFoo()
místo foo()
.
Zkratky
Jména, která obsahují zkratky, by měla zkratku považovat za normální slovo a podle potřeby používat pouze velké první písmeno.
To platí i pro dvoupísmenné zkratky, například Id
.
Například getHtmlApiSource
na rozdíl od "getHTMLAPISource".
jQuery
Odlište uzly DOM od objektů jQuery předponou proměnným znakem dolaru, pokud budou obsahovat objekt jQuery, např. $foo = $( '#bar' )
.
To pomáhá omezit chyby tam, kde podmínky používají nesprávné podmíněné kontroly, jako je if ( foo )
namísto if ( $foo.length )
.
Tam, kde metody DOM často vracejí hodnotu null (což je nepravda), metody jQuery vracejí prázdný objekt kolekce (které jsou, stejně jako nativní pole a další objekty v JavaScriptu, pravdivé).
npm
Při publikování samostatného projektu na npmjs.org zvažte jeho publikování pod jmenným prostorem @wikimedia
.
Všimněte si, že některé samostatné projekty, které jsou zaměřeny na použití mimo komunitu Wikimedia a mají dostatečně jedinečný název, v současnosti používají název balíčku bez jmenných prostorů (např. "oojs" a "visualeditor").
T239742
Vytváření prvků
Chcete-li vytvořit prostý prvek, použijte jednoduchou syntaxi <tag>
v konstruktoru jQuery:
$hello = $( '<div>' )
.text( 'Hello' );
Při vytváření prvků na základě názvu značky z proměnné (která může obsahovat libovolný html):
// Načíst 'span' nebo 'div' atd.
tag = randomTagName();
$who = $( document.createElement( tag ) );
$('<a title="valid html" href="#syntax">like this</a>');
používejte pouze tehdy, když potřebujete analyzovat HTML (na rozdíl od vytváření prostého prvku).
Sbírky
Různé typy kolekcí někdy vypadají podobně, ale mají odlišné chování a mělo by se s nimi tak zacházet. Tento zmatek je většinou způsoben tím, že pole v JavaScriptu vypadají hodně jako pole v jiných jazycích, ale ve skutečnosti jsou pouze rozšířením Object. Používáme následující konvence:
Zadání | Pole | Obyčejné objekty | Objekty jQuery |
---|---|---|---|
Deklarace a prázdná inicializace | x = [];
|
x = {};
|
$x = $( [] );
|
Přístupová hodnota | x[ 0 ];
|
x.key;
|
element = $x[ 0 ]; or $y = $x.eq( 0 );
|
Velikost | x.length;
|
Object.keys( x ).length;
|
$x.length;
|
Opakování | for ( i = 0; i < x.length; i++ ) {} or: x.forEach( ( value, i ) => {} );
|
for ( key in x ) {}
|
$x.each( ( i, element ) => {} );
|
Nepoužívejte smyčku for-in
k opakování přes pole (na rozdíl od prostého objektu), protože for-in
bude mít za následek mnoho neočekávaných chování, včetně: Klíčů jako řetězců, nestabilního pořadí iterací, indexů může přeskakovat mezery, opakování může zahrnovat jiné nečíselné znaky vlastnosti.
Úložiště
Klíče v localStorage anebo sessionStorage by měly být přístupné přes mw.storage
nebo mw.storage.session
.
Klíče
eys by měl začínat mw
a používat Camel Case anebo spojovníky.
Nepoužívejte podtržítka ani jiné oddělovače.
Příklady skutečných klíčů:
mwuser-sessionId
mwedit-state-templatesUsed
mwpreferences-prevTab
Dejte si pozor na to, že na rozdíl od souborů cookie přes mw.cookie není ve výchozím nastavení přidána žádná wiki předpona nebo předpona cookie.
Pokud se hodnoty musí lišit podle wiki, musíte ručně zahrnout wgCookiePrefix
jako součást klíče.
Hodnoty
Hodnoty musí být řetězce. Pozor, pokus o uložení jiných typů hodnot se tiše přetypuje na řetězec (např. z false
se stane "false"
).
Prostor je omezený. Kde je to možné, používejte krátké a výstižné hodnoty před objektovými strukturami. Několik příkladů:
- Pro booleovský stav (pravda/nepravda, rozbaleno/sbaleno) použijte "1" nebo "0".
- Hodnoty, které jsou vždy čísly, je uložte tak, jak jsou, a na cestě ven přetypujte s
Number
(vyhněte separseInt
). - Hodnoty, které jsou vždy řetězce, uložte tak, jak jsou.
- U seznamů softwarově definovaných hodnot zvažte řetězce oddělené čárkami nebo svislou čarou, abyste snížili prostor a náklady na zpracování.
- Pro seznamy hodnot, které mohou být vytvořeny uživatelem nebo jsou jinak složité povahy, použijte JSON.
Strategie vylučování
Pamatujte, že místní úložiště nemá ve výchozím nastavení žádnou strategii vylučování. Proto je třeba se vyhnout následujícímu:
- Nepoužívejte jako součást názvu klíče vstup generovaný uživatelem.
- Vyhněte se klíčům obsahujícím identifikátory entit generovaných uživateli (např. uživatelská jména, názvy kategorií, ID stránek nebo jiné proměnné poskytnuté uživatelem nebo systémem).
- Obecně se vyhněte přístupům, které zahrnují vytváření potenciálně velkého počtu klíčů úložiště.
Pokud například funkce potřebuje uložit stav proměnné entity (např. aktuální stránky), může mít smysl použít jeden klíč pro tuto funkci jako celek a omezit uložené informace pouze na několik posledních iterací (LRU). . Mírné zvýšení nákladů na vyhledání (celý klíč namísto samostatných menších) se považuje za vhodné, protože jinak by počet klíčů nekontrolovatelně rostl.
I když klíče nezávisí na vstupu uživatele, možná budete chtít pro svou funkci použít jeden klíč, protože jinak budou mít předchozí verze vašeho softwaru uložená data, která nebudete moci vyčistit. Použitím jediného klíče jej můžete přepínat způsobem, který přirozeně nepřetrvává neznámé dílčí vlastnosti.
Použití sledovacího klíče je také anti-vzor a nevyhne se výše uvedeným problémům, protože by mohlo dojít k úniku kvůli závodním podmínkám ve webovém úložišti HTML5, které je sdíleno a není atomické mezi více otevřenými kartami prohlížeče.
Když má být funkce místního úložiště odstraněna, nezapomeňte nejprve implementovat strategii vystěhování, abyste odstranili staré hodnoty. Obvykle se mw.requestIdleCallback používá k elegantnímu vyhledání klíče a jeho odstranění. Viz T121646 pro škálovatelnější přístup.
Osobní údaje
Neukládejte do místního úložiště osobní údaje, které zůstanou, když se uživatel odhlásí nebo zavře prohlížeč. Použijte místo toho úložiště relací. Podívejte se na stránku T179752.
Asynchronní kód
Asynchronní kód by se měl řídit standardem Promise a být s ním kompatibilní.
Pokud definujete asynchronní metodu pro volání jiného kódu, můžete interně vytvořit vrácený objekt thenable pomocí $.Deferred nebo nativního Promise.
Když zavoláte asynchronní metodu, použijte pouze standardní metody kompatibilní s Promise, jako jsou then()
a catch()
.
Vyhněte se používání metod specifických pro jQuery, jako je done()
nebo fail()
, které by mohly přestat fungovat bez varování, pokud metoda, kterou voláte, interně přejde z $.Deferred na nativní Promise.
Všimněte si, že ve zpětných voláních done
a fail
existují také jemné starší chování.
Při migraci stávajícího kódu z done()
na then()
věnujte zvýšenou pozornost, protože to může způsobit, že kód přestane správně fungovat.
Konkrétně, zpětná volání done
a fail
vyvolají vaše zpětné volání synchronně, pokud bylo odložené volání již vyřízeno v době, kdy připojíte zpětné volání.
To znamená, že vaše zpětné volání může být vyvoláno před dokončením příkazu připojení.
Například:
function getSqrt( num ) { return $.Deferred().resolve( Math.sqrt( num ) ); }
console.log( "A" );
getSqrt( 49 ).done( ( val ) => {
console.log( "C" ); // může být A C B nebo A B C
} );
console.log( "B" );
console.log( "A" );
getSqrt( 49 ).then( ( val ) => {
console.log( "C" ); // vždy A B C
} );
console.log( "B" );
const y = getSqrt( 49 ).then( ( val ) => {
console.log( y.state(), val ); // "vyřešeno", 7
} );
const x = getSqrt( 49 ).done( ( val ) => {
console.log( x.state(), val ); // Nezachycený TypeError: x je nedefinováno
} );
const z = getSqrt( 49 );
z.done( ( val ) => {
console.log( x.state(), val ); // "vyřešeno", 7
} );
jQuery
jQuery is still supported in MediaWiki and it is a useful tool, but it is slow and dated, and there are some functions and patterns to avoid. The following emit warnings or errors in eslint-config-wikimedia.
- Avoid functions in the jQuery library that are deprecated, since these will be removed from jQuery at some point or already have been. Examples:
.addSelf
,.bind
,.unbind
,.boxModel
,.browser
,.camelCase
,.context
,.delegate
,.undelegate
, etc.[7] - Avoid functions in the jQuery library that have ES5/ES6 equivalents. The ES5/ES6 equivalents are faster. Examples:
.each
,.grep
,.inArray
,.map
,.trim
,.error
,.extend
,.noop
.[8] - Avoid functions in the jQuery library that have CSS equivalents. The CSS equivalents are faster. Examples:
.animate
,.stop
,.finish
,.fadeIn
,.fadeOut
,.fadeTo
,.fadeToggle
,.slideDown
,.slideToggle
,.slideUp
, etc.[8] - Avoid using jQuery to query the DOM, for performance reasons and to avoid selecting incorrect elements by mistake. Prefer hooks such as
mw.hook( 'wikipage.content' ).add( ( $content ) => {
, which provides a$content
element that you can do.find()
s on. When you create elements, store them in a variable, then retrieve them later using the variable or$variable.find()
. If you need to, you can make exceptions to this from time to time using comments such as// eslint-disable-next-line no-jquery/no-global-selector
. - Avoid sizzle selectors, for performance reasons and because some sizzle syntax is already deprecated. For example, avoid
$( '#mw-specialmute-form input:checkbox' )
and$input.is( ':visible' )
. - Avoid
.globalEval
. - Generate complex HTML using multiple jQuery functions instead of just a string in the
$()
function. For example, prefer$( '<a>' ).attr( 'href', 'https://test.com' ).text( 'Test' )
to$( '<a href="https://test.com">Test</a>' )
. The latter is prone to errors that linters cannot detect, and triggers jQuery's HTML parser, which is slow.[11]
Závěrečné poznámky
Opětovné použití modulů ResourceLoader
Neobjevujte znovu kolo. Mnoho funkcí JavaScriptu a utilit souvisejících s MediaWiki se dodává s jádrem MediaWiki, které jsou stabilní a můžete se na ně (doslova) spolehnout. Než nasadíte svůj vlastní kód, podívejte se na ResourceLoader/Core modules .
Úskalí
- Buďte opatrní, abyste zachovali kompatibilitu s jazyky psanými zleva doprava a zprava doleva (tj.
float: right
nebotext-align: left
), zejména při stylování textových kontejnerů. Vložení těchto deklarací do souboru CSS umožní jejich automatické převrácení pro jazyky RTL z CSSJanus na ResourceLoader . - Použijte přiměřeně
attr()
aprop()
.
Přečtěte si více: - Konzistentní hodnoty selektoru citovat atribut:
[foo="bar"]
místo[foo=bar]
(jqbug 8229). - Od jQuery 1.4 má konstruktor jQuery novou funkci, která umožňuje předat objekt jako druhý argument, například:
$( '<div>', { foo: 'bar', click: () => {}, css: { .. } } );
. Toto nepoužívejte. Ztěžuje sledování kódu, selhává u atributů (jako je 'size' (velikost)), které jsou také metodami, a je nestabilní kvůli tomuto míšení metod jQuery s atributy prvků. Budoucí metoda jQuery nebo plugin nazvaný "title" může převést prvek na nadpis, což znamená, že atribut title již nelze nastavit touto metodou. Buďte explicitní a volejte.attr()
,.prop()
,.on()
atd. přímo.
Použijte CSS pro úpravu stylů mnoha prvků
Neaplikujte styl na mnoho prvků najednou. Oslabuje to výkon.
Místo toho použijte společnou rodičovskou třídu (nebo jednu přidejte) a použijte CSS v souboru .css
nebo .less
.
Díky ResourceLoaderu se to vše načte ve stejném požadavku HTTP, takže za samostatný soubor CSS nedochází k žádnému snížení výkonu.
Nenastavujte CSS do inline atributů "style", nevkládejte ani prvky "style" z JS.
Poznámky pod čarou
- JavaScript Style Guide, Přispějte do jQuery
- Kódové konvence pro JavaScript, Douglas Crockford
- Styl programování a váš mozek, Douglas Crockford na YouTube
- ↑ Rozhodněte, kterou metodu "eslint ignore" použít, duben 2020.
- ↑ T50886: Odstraňte zastaralé uzávěry souborů, duben 2019.
- ↑ http://benalman.com/news/2010/11/immediately-invoked-function-expression/
- ↑ $url Mám substr(), substring() nebo slice()?
- ↑ Řetězce v JavaScriptu, Zvládnutí JS.
- ↑ Change 158108 - mediawiki/core, , gerrit.wikimedia.org
- ↑ https://github.com/wikimedia/eslint-config-wikimedia/blob/91e9a0ba09bc77471d21c1e92d24fa190109a08e/jquery.json#L8
- ↑ 8.0 8.1 https://github.com/wikimedia/eslint-config-wikimedia/blob/91e9a0ba09bc77471d21c1e92d24fa190109a08e/jquery.json#L11-L28
- ↑ https://github.com/wikimedia/eslint-plugin-no-jquery/blob/master/docs/rules/no-global-selector.md
- ↑ https://github.com/wikimedia/eslint-plugin-no-jquery/blob/master/docs/rules/no-class-state.md
- ↑ https://github.com/wikimedia/eslint-plugin-no-jquery/blob/master/docs/rules/no-parse-html-literal.md