web-dev-qa-db-fra.com

Faire un court alias pour Document.QuerySelectorallall

Je vais courir le document.QuerySelectorallall () beaucoup, et j'aimerais un alias racnorifique pour cela.

var queryAll = document.querySelectorAll

queryAll('body')
TypeError: Illegal invocation

Ne fonctionne pas. Tandis que:

document.querySelectorAll('body')

Toujours fait. Comment puis-je faire fonctionner l'alias?

48
mikemaccana

Cela semble fonctionner:

var queryAll = document.querySelectorAll.bind(document);

bind renvoie une référence à la fonction querySelectorAll, modifiant le contexte de "Ceci" à l'intérieur de la méthode QuerySelectorall pour être l'objet de document.

La fonction de liaison n'est prise en charge que dans IE9 + (et tous les autres navigateurs) - https://developer.mozilla.org/en-us/docs/javascript/reference/global_objects/function/bind


Mise à jour: En fait, vous pouvez créer des raccourcis sur une gamme complète de méthodes de document comme celle-ci:

var query = document.querySelector.bind(document);
var queryAll = document.querySelectorAll.bind(document);
var fromId = document.getElementById.bind(document);
var fromClass = document.getElementsByClassName.bind(document);
var fromTag = document.getElementsByTagName.bind(document);
77
Sunday Ironfoot

L'interprète JavaScript jette une erreur car querySelectorAll() doit être invoqué dans le contexte du document.

La même erreur est lancée lorsque vous essayez d'appeler console.log() aliased.

Vous devez donc envelopper comme ça:

 function x(selector) {
     return document.querySelectorAll(selector);
 }
14
zlebnik

Ma solution couvre les quatre cas d'utilisation suivants:

  • document.QuerySelector (...)
  • document.QuerySelectorallall (...)
  • element.QuerySelector (...)
  • element.QuerySelectorallall (...)

Le code:

let doc=document,
    qsa=(s,o=doc)=>o.querySelectorAll(s),
    qs=(s,o=doc)=>o.querySelector(s);

En termes de paramètres, le sélecteur s est requis, mais l'objet élément du conteneur o est facultatif.

Usage:

  • qs("div"): interroge l'ensemble du document pour le premier div, renvoie cet élément
  • qsa("div"): interroge tout le document pour tous les divs, renvoie une nodéliste de tous ces éléments
  • qs("div", myContainer): requêtes juste dans l'élément Mycontainer pour le premier div, renvoie cet élément
  • qsa("div", myContainer): requêtes juste dans l'élément Mycontainer pour tous les DIV, renvoie une nodéliste de tous ces éléments

Pour rendre le code légèrement plus court (mais pas tout aussi efficace), le code qs pourrait être écrit comme suit:

let qs=(s,o=doc)=>qsa(s,o)[0];

Le code ci-dessus utilise des fonctionnalités ES6 (let, fonctions fléchées et valeurs de paramètre par défaut). Un équivalent ES5 est:

var doc=document,
    qsa=function(s,o){return(o||doc).querySelectorAll(s);},
    qs=function(s,o){return(o||doc).querySelector(s);};

ou la version équivalente plus courte mais moins efficace de qs:

var qs=function(s,o){return qsa(s,o)[0];};

Vous trouverez ci-dessous une démonstration de travail. Pour que cela fonctionne sur tous les navigateurs, il utilise la version ES5, mais si vous allez utiliser cette idée, rappelez-vous que la version ES6 est plus courte:

var doc = document;

var qs=function(s,o){return(o||doc).querySelector(s);},
    qsa=function(s,o){return(o||doc).querySelectorAll(s);}

var show=function(s){doc.body.appendChild(doc.createElement("p")).innerHTML=s;}

//           ____demo____       _____long equivalent______      __check return___      _expect__ 
//          |            |     |                          |    |                 |    |         |

let one   = qs("div");      /* doc.querySelector   ("#one") */ show(one  .id    ); // "one"
let oneN  = qs("div",one);  /* one.querySelector   ("div")  */ show(oneN .id    ); // "oneNested"
let many  = qsa("div");     /* doc.querySelectorAll("div")  */ show(many .length); // 3
let manyN = qsa("div",one); /* one.querySelectorAll("div")  */ show(manyN.length); // 2
<h3>Expecting "one", "oneNested", 3 and 2...</h3>
<div id="one">
  <div id="oneNested"></div>
  <div></div>
</div>
8
Andrew Willems

Cela fonctionnerait, vous devez invoquer l'alias à l'aide de call() ou apply() avec le contexte approprié.

func.call(context, arg1, arg2, ...) 
func.apply(context, [args]) 

var x = document.querySelectorAll;
x.call(document, 'body');
x.apply(document, ['body']);
7
Gabe

Une réponse commune est d'utiliser $ et $$ pour querySelector et querySelectorAll. Cet alias imite celle de JQuery.

Exemple:

$ = document.querySelector.bind(document)
$$ = document.querySelectorAll.bind(document)

$('div').style.color = 'blue'
$$('div').forEach(div => div.style.background = 'orange')
div {
  margin: 2px;
}
<div>
  test
</div>
<section>
  <div>
    hello
  </div>
  <div>
    foo
  </div>
</section>
7
aloisdg

J'ai pris l'approche de @david Muller et je l'a doublé à l'aide d'une Lambda

let $ = (selector) => document.querySelector(selector);
let $all = (selector) => document.querySelectorAll(selector);

Exemple:

$('body');
// <body>...</body>
5
svarog
function x(expr)
{
    return document.querySelectorAll(expr);
}
4
David Müller

Voici mon emporter dessus. Si le sélecteur a plusieurs correspondances, renvoyez comme querySelectorAll. Si ony, une correspondance est trouvée, rendez-vous comme querySelector.

function $(selector) {
  let all = document.querySelectorAll(selector);
  if(all.length == 1) return all[0];
  return all;
}

let one = $('#my-single-element');
let many = $('#multiple-elements li');

mise à jour de 2019

Aujourd'hui, j'ai fait une nouvelle prise sur le problème. Dans cette version, vous pouvez également utiliser une base comme celle-ci:

let base = document.querySelectorAll('ul');

$$('li'); // All li
$$('li', base); // All li within ul

fonctions

function $(selector, base = null) {
  base = (base === null) ? document : base;
  return base.querySelector(selector);
}

function $$(selector, base = null) {
  base = (base === null) ? document : base;
  return base.querySelectorAll(selector);
}
1
Jens Törnell
function $(selector, base = null) {
  base = (base === null) ? document : base;
  return base.querySelector(selector);
}

function $$(selector, base = null) {
  base = (base === null) ? document : base;
  return base.querySelectorAll(selector);
}

Pourquoi pas plus simple ??? :

let $ = (selector, base = document) => {
  let elements = base.querySelectorAll(selector);
  return (elements.length == 1) ? elements[0] : elements;
}
0
Marek Lisiecki