Maison  >  Article  >  interface Web  >  DOM optimisé pour JavaScript

DOM optimisé pour JavaScript

php中世界最好的语言
php中世界最好的语言original
2018-03-19 16:27:091870parcourir

Cette fois je vais vous présenter l'optimisation JavaScript du DOM, et quelles sont les précautions pour optimiser le DOM en JavaScript Voici des cas pratiques, jetons un coup d'oeil.

L'optimisation du DOM commence par redessiner et réorganiser, il y a très longtemps...

Redessiner et réorganiser

1.1 Qu'est-ce que le redessin et la réorganisation

Le redessin fait référence à certaines modifications de style, la position et la taille des éléments n'ont pas changé

Le réarrangement signifie que la position ou la taille d'un élément a changé et que le navigateur doit recalculer l'arborescence de rendu. Une fois la nouvelle arborescence de rendu établie, le navigateur redessinera les éléments concernés.

1.2 Page de rendu du navigateur

Lorsque vous vous rendez à un entretien, une question vous sera toujours posée, c'est-à-dire « Entrez une ligne de l'url dans le navigateur." Que s'est-il passé ? ", la réponse à cette question implique non seulement la connaissance du réseau mais également la question du rendu de la page par le navigateur. Lorsque notre navigateur reçoit la réponse de la page du serveur, il commence le rendu ligne par ligne. Lorsqu'il rencontre du CSS, il calcule de manière asynchrone la valeur de l'attribut, puis continue d'analyser le dom. Une fois l'analyse terminée, une arborescence DOM est créée. formé, qui sera asynchrone Le style calculé (boîte de style) est combiné avec l'arborescence DOM pour former un arbre de rendu, qui est ensuite dessiné sur la page par le navigateur. La différence entre l'arborescence DOM et l'arborescence de rendu est que les nœuds avec le style display:none; seront dans l'arborescence DOM mais pas dans l'arborescence de rendu. Après le dessin, le navigateur commence à analyser le fichier js et détermine s'il doit être redessiné et redistribué en fonction du js.

1.3 Raisons du redessin et du refusion

Facteurs qui provoquent le redessin :

  • La modification de la visibilité, du contour, de la couleur d'arrière-plan et d'autres attributs de style ne modifie pas la taille, la position, etc. de l'élément. Le navigateur se redessinera en fonction des nouvelles propriétés de l'élément.

Facteurs provoquant un réarrangement :

  • Changement de contenu

    • Modifications du texte ou modifications de la taille de l'image

  • Modifications des propriétés géométriques des éléments DOM

    • Par exemple Lorsque les valeurs de largeur et de hauteur d'un élément DOM sont modifiées, les nœuds pertinents dans l'arborescence de rendu d'origine deviendront invalides et le navigateur réorganisera les nœuds pertinents dans l'arborescence de rendu en fonction du DOM modifié. Si les attributs géométriques du nœud parent changent, les positions de ses nœuds enfants et des nœuds frères suivants seront recalculées, provoquant une série de réarrangements.

  • Changements de structure de l'arborescence DOM

    • Ajouter un nœud DOM, modifier la position du nœud DOM et La suppression d'un nœud est une modification de l'arborescence DOM, qui entraînera un réarrangement des pages. La disposition du navigateur est un processus de haut en bas. La modification de l'élément actuel n'affectera pas les éléments qui ont été parcourus avant celui-ci. Cependant, si un nouvel élément est ajouté devant tous les nœuds, tous les éléments suivants seront réorganisés.

  • Obtention de certains attributs

    • En plus des modifications directes dans l'arbre de rendu, lors de l'obtention de certaines valeurs d'attribut, le Un réarrangement du navigateur se produira également pour obtenir la valeur correcte. Ces attributs incluent : offsetTop, offsetLeft, offsetWidth, offsetHeight, scrollTop, scrollLeft, scrollWidth, scrollHeight, clientTop. , clientLeft, clientWidth, clientHeight, getComputedStyle().

  • Modifications de la taille de la fenêtre du navigateur

    • Les modifications de la taille de la fenêtre affecteront les modifications de la taille des éléments dans l'ensemble de la page Web, c'est-à-dire que les éléments DOM changent les propriétés de la collection, provoquant ainsi un réarrangement.

  • L'apparition de la barre de défilement (va déclencher la reflow de toute la page)

Bref, il faut savoir que js est monothread, le redessinage et la redistribution bloqueront les opérations de l'utilisateur et affecteront les performances de la page Web. Lorsqu'une page est redessinée et redistribuée plusieurs fois, comme l'écriture d'une minuterie pour modifier la largeur et la hauteur des éléments de la page toutes les 500 ms, la page peut devenir de plus en plus bloquée, nous devons donc réduire autant que possible le redessinage et la redistribution. Ensuite, notre optimisation du DOM repose également sur ce point de départ.

2. Optimisation

2.1 Réduire les accès

Réduire le nombre d'accès passe naturellement par mettre en cache des éléments, mais faites attention >

Cela ne met pas en cache ele. Chaque fois que ele est appelé, cela équivaut à visiter le nœud avec l'identifiant de ele.
var ele = document.getElementById('ele');

2.1.1 Cache NodeList

Nous pouvons utiliser foods[i] pour accéder au i-ième élément avec la nourriture de classe, mais les aliments ici ne le sont pas Un tableau, mais une NodeList. NodeList est un tableau de type tableau qui stocke certains nœuds ordonnés et peut accéder à ces nœuds par position. Les objets NodeList sont dynamiques et une requête basée sur le document est exécutée à chaque accès. Par conséquent, nous devons minimiser le nombre de visites sur NodeList et nous pouvons envisager de mettre en cache la valeur de NodeList.
var foods = document.getElementsByClassName('food');

Et comme NodeList change dynamiquement, s'il n'est pas mis en cache, cela peut provoquer une boucle infinie, comme l'ajout d'éléments tout en obtenant la longueur de NodeList.
// 优化前var lis = document.getElementsByTagName('li');for(var i = 0; i < lis.length; i++) {     // do something...  }// 优化后,将length的值缓存起来就不会每次都去查询length的值var lis = document.getElementsByTagName('li');for(var i = 0, len = lis.length; i < len; i++) {     // do something...  }

2.1.2 Changer le sélecteur

Il existe deux manières les plus courantes d'obtenir des éléments, getElementsByXXX() et queryselectorAll(). La différence entre ces deux sélecteurs est très grande. get Dynamic collection, cette dernière consiste à obtenir une collection statique, par exemple.

Les opérations sur les collections statiques n'entraîneront pas de réinterrogation des documents, ce qui est plus optimisé que les collections dynamiques.
// 假设一开始有2个livar lis = document.getElementsByTagName('li');  // 动态集合var ul = document.getElementsByTagName('ul')[0]; 
for(var i = 0; i < 3; i++) {
    console.log(lis.length);    var newLi = document.createElement('li'); 
    ul.appendChild(newLi);
}// 输出结果:2, 3, 4var lis = document.querySelector('li');  // 静态集合 var ul = document.getElementsByTagName('ul')[0]; 
for(var i = 0; i < 3; i++) {
    console.log(lis.length);    var newLi = document.createElement('li'); 
    ul.appendChild(newLi);
}// 输出结果:2, 2, 2

2.1.3 Évitez les boucles inutiles

// 优化前
for(var i = 0; i < 10; i++) {
    document.getElementById('ele').innerHTML += 'a';
Le code pré-optimisé accède à l'élément ele 10 fois, tandis que le code optimisé n'y accède qu'une seule fois, ce qui constitue une énorme amélioration efficacité.
} 
// 优化后 
var str = ''; 
for(var i = 0; i < 10; i++) {
    str += 'a'; 
}
document.getElementById('ele').innerHTML = str;

2.1.4 Délégué d'événement

Les fonctions d'événement dans js sont toutes des objets. S'il y a trop de fonctions d'événement, cela occupera beaucoup de mémoire, et plus il y aura d'éléments DOM liés. à l'événement, plus il faudra de temps pour accéder aux heures dom, il y aura également un retard dans le temps de préparation interactive de la page. Par conséquent, la délégation d'événements est née. La délégation d'événements utilise le bouillonnement d'événements pour gérer tous les événements d'un certain type en spécifiant un seul programme

gestionnaire d'événements

.

Avant la délégation d'événement, nous avons visité lis.length fois li, mais après avoir utilisé la délégation d'événement, nous n'avons visité ul qu'une seule fois.
// 事件委托前var lis = document.getElementsByTagName('li');for(var i = 0; i < lis.length; i++) {
   lis[i].onclick = function() {
      console.log(this.innerHTML);
   };  
}    
// 事件委托后var ul = document.getElementsByTagName('ul')[0];
ul.onclick = function(event) {
   console.log(event.target.innerHTML);
};

2.2 Réduire le redessinage et le réarrangement

2.2.1 Modifier plusieurs styles d'un nœud dom

Nous voulons pour modifier la largeur et la hauteur d'un élément p L'approche habituelle peut être la suivante : redessiner. Nous avons dit que l'optimisation consiste à réduire le nombre de visites et le nombre de redessins et de réapprovisionnements. A partir de ce point de départ, peut-on accéder à l'élément une seule fois et réduire le nombre de réapprovisionnements à 1 ? Évidemment, c'est possible, nous pouvons écrire une classe en CSS

De cette façon, nous pouvons utiliser plusieurs styles à la fois

 p = document.getElementById('p1'
2.2.2 Modifier par lots les styles de nœuds dom

Le code ci-dessus est pour un nœud DOM. Et si nous voulons changer le style d'une collection DOM ?
/* css
.change {
    width: 220px;
    height: 300px;
}*/document.getElementById('p').className = 'change';

La première méthode qui vient à l'esprit consiste à parcourir la collection et à ajouter un nom de classe à chaque nœud. Pensez-y encore, cela ne signifie-t-il pas que vous avez visité le nœud dom plusieurs fois ? Pensez à la différence entre l'arborescence DOM et l'arborescence de rendu mentionnée au début de l'article. Si l'attribut d'affichage d'un nœud est nul, alors ce nœud n'existera pas dans l'arborescence de rendu, ce qui signifie que le fonctionnement de ce nœud existera. n'affectera pas l'arbre de rendu et ne provoquera pas de redessinage et de réorganisation, sur la base de cette idée, nous pouvons réaliser une optimisation :

Afficher l'élément parent de la collection à modifier : aucun ;

  • 之后遍历修改集合节点

  • 将集合父元素display: block;

  • // 假设增加的class为.changevar lis = document.getElementsByTagName('li');  
    var ul = document.getElementsByTagName('ul')[0];
    ul.style.display = 'none';for(var i = 0; i < lis.length; i++) {
        lis[i].className = 'change';  
    }
    ul.style.display = 'block';

    3、总结

    • 减少访问dom的次数

      • 缓存节点属性值

      • 选择器的使用

      • 避免不必要的循环

      • 事件委托

    • 减少重绘与重排

      • 使用className改变多个样式

      • 使父元素脱离文档流再恢复

    相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

    推荐阅读:

    Vue的计算属性

    Webpack模块的使用

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn