Maison  >  Article  >  interface Web  >  Troisième sujet JavaScript : Anti-tremblement

Troisième sujet JavaScript : Anti-tremblement

coldplay.xixi
coldplay.xixiavant
2021-03-04 09:56:003164parcourir

Troisième sujet JavaScript : Anti-tremblement

Table des matières

  • Pourquoi un anti-secousse est nécessaire
  • 2. Anti-shake Le principe de
  • 3. Mise en œuvre simple de l'anti-shake
  • 4. Anti-shake avancé
  • Écrit à la fin

(Recommandations d'apprentissage gratuites associées : tutoriel vidéo javascript)

1. Pourquoi l'anti-tremblement est nécessaire

  • Les opérations de fonction à haute fréquence peuvent avoir des effets néfastes
  • Tels que : redimensionner, faire défiler, mousedown, mousemove, keyup, keydown...

À cette fin, prenons un exemple de code pour comprendre comment l'événement se déclenche fréquemment :

Nous écrivons un fichier index.html :

    <meta>
    <meta>
    <meta>
    <title>Document</title>
    <title>debounce</title>
    <style>
        #wrapper {
            width: 100%;
            height: 200px;
            line-height: 200px;
            text-align: center;
            color: #fff;
            background-color: #444;
            font-size: 30px;
        }
    </style>
    <p></p>
    <script>
        var count = 1;
        var op = document.getElementById("wrapper");

        function getUserAction() {
            op.innerHTML = count++;
        }

        op.onmousemove = getUserAction;
    </script>

Il se déclenche près de 100 fois en glissant de gauche à droite getUserActionFonction ! Regardez le Gif suivant :

Troisième sujet JavaScript : Anti-tremblement

Comme cet exemple est très simple, le navigateur peut réagir complètement, mais supposons :

  • Il se déclenche extrêmement fréquemment Élevé, 2000 fois par minute, et implique beaucoup de calculs de position, d'opérations DOM, etc.
  • Il existe des requêtes d'interface Le temps d'exécution d'une seule fonction est long, mais l'intervalle de déclenchement de chaque fonction est très. fermer.

Ce type d'interaction qui met trop de pression sur le navigateur ou le serveur en peu de temps doit être optimisé. Afin de résoudre ce problème, il existe généralement deux solutions :

    Anti-secousse anti-rebond
  • Limitation des gaz
Leurs objectifs sont :

Réduire la fréquence de déclenchement d'une fonction pour améliorer les performances ou éviter le gaspillage de ressources.

2. Le principe de l'anti-shake

Aujourd'hui nous allons nous concentrer sur la mise en place de l'anti-shake.

Le principe de l'anti-shake est le suivant : même si vous déclenchez un événement, je ne l'exécuterai pas tant que l'événement ne se déclenchera pas

. Par exemple : n秒无操作后

Nous stipulons que

est la norme pour l'anti-shake, puis : 3s

    La première demande d'exécution d'un événement - à ce moment le compte à rebours est de 3s
  1. Compte à rebours 2s
  2. Compte à rebours 1s
  3. L'événement se déclenche à nouveau à 0,5s - A cet instant, compte à rebours 3s
  4. ...rien ne se passe dans les 3s
  5. Événement d'exécution, partagé 5,5s

Troisième sujet JavaScript : Anti-tremblement

3. Implémentez un anti-shake par vous-même

3.1 Première édition

Nous Sur la base des idées de base mentionnées dans la section précédente, implémentez la première version du code :

function debounce(func, wait) {
    var timer;
    return function () {
        clearTimeout(timer)
        timer = setTimeout(func, wait);
    }}
Si nous voulons l'utiliser, prenons l'exemple de la première section à titre d'exemple :

op.onmousemove = debounce(getUserAction, 2000);
A ce stade vous pouvez le tester à nouveau. Désormais, lorsque l'événement continue de se produire, l'événement ne se déclenchera qu'après 2 secondes d'arrêt complet :

En écrivant ceci, comme exigence pour certains événements à haute fréquence, c'est terminé. Jetons un coup d'œil à son effet :

Troisième sujet JavaScript : Anti-tremblement

3.2 Deuxième édition

Comme nous le savons tous, lorsqu'un nœud dom déclenche un événement, celui-ci pointe vers lui-même. Dans cet exemple, il pointe vers

, mais dans ce cas : Jetons un coup d'œil à op

var count = 1;var op = document.getElementById("op");function getUserAction() {
    op.innerHTML = count++;
    console.log('this', this); // 此时输出 Window...}op.onmousemove = debounce(getUserAction, 2000);function debounce(func, wait) {
    var timer;
    return function () {
        clearTimeout(timer)
        timer = setTimeout(func, wait);
    }}
Après tout, il a été enveloppé par une couche de fonctions anonymes. Cela pointe déjà vers window In. afin de réduire l'impact, nous essayons de le corriger

function debounce(func, wait) {
    var timer;
    return function () {
        var _this = this; // 记录当前this

        clearTimeout(timer)
        timer = setTimeout(function(){
            func.apply(_this); //将 func的this改为_this
        }, wait);
    }}
La troisième version

résout ce problème de pointage Notre fonction n'est toujours pas assez "parfaite" En JavaScript, la fonction de traitement des événements. fournira l'objet

, que nous appelons e en abrégé. event

// 使用了 debouce 函数function getUserAction(e) {
    console.log(e); // undefined
    op.innerHTML = count++;};
Afin de garantir son authenticité, nous allons modifier la troisième version :

var count = 1;var op = document.getElementById("op");function getUserAction(e) {
    op.innerHTML = count++;
    console.log('e', e); // MouseEvent}op.onmousemove = debounce(getUserAction, 2000);function debounce(func, wait) {
    var timer;
    return function () {
        var _this = this; // 记录当前this
        var arg = arguments; // 记录参数
        clearTimeout(timer)
        timer = setTimeout(function () {
            func.apply(_this, arg); //将 func的this改为_this
        }, wait);
    }}
Jusqu'à présent, nous avons ajouté à la fonction tout en conservant autant que possible les capacités originales de l'événement Dom . Avec l'effet anti-secousse, cela peut résoudre la plupart de nos problèmes anti-secousses de développement quotidien, mais nous devons être plus "parfaits"

Troisième sujet JavaScript : Anti-tremblement

4. Anti-tremblement avancé

4.1 Exécuter immédiatement

Cette exigence est :

    Exécuter immédiatement
  • Garder
  • secondes de période vide n
  • Définissez la
  • deuxième période vide après n
En pensant à cette exigence, cela a du sens. Ensuite, nous ajoutons un paramètre

pour déterminer s'il est exécuté immédiatement. immediate

function debounce(func, wait, immediate) {
    var timer;

    return function () {
        var _this = this;
        var args = arguments;

        if (timer) clearTimeout(timer); // 常规流程,间隔内触发时清掉重置定时
        if (immediate) {
            // 如果已经执行过,不再执行
            var callNow = !timer; // 1. callNow 初始值是 true, 同步立即执行;随后 timer 才开始执行
            timer = setTimeout(function(){
                timer = null; // wait 期间,timer 是一个 ID 数字,所以 callNow 为 false,func 在此期间永远不会执行
            }, wait) // wait 之后,timer 赋值 null,callNow 为 true,func 又开始立即执行。
            if (callNow) func.apply(_this, args)
        }
        else {
            timer = setTimeout(function(){
                func.apply(_this, args)
            }, wait);
        }
    }}
Jetons un coup d'œil à son effet à ce moment :

Troisième sujet JavaScript : Anti-tremblement

4.2 Ajouter une vérification simple

function debounce(func, wait, immediate) {
    var timer;
    // 检查函数
    if (typeof func !== 'function') {
        throw new TypeError('Expected a function');
    }
    // 保证wait存在
    wait = +wait || 0;

    const debounced = function () {
        var _this = this;
        var args = arguments;

        if (timer) clearTimeout(timer); // 常规流程,间隔内触发时清掉重置定时
        if (immediate) {
            // 如果已经执行过,不再执行
            var callNow = !timer; // 如果不存在定时器,则callNow为true
            timer = setTimeout(function () {
                timer = null; // 为了保证之后的时效性,手动添加timer
            }, wait)
            // 因为不存在timer,证明是首次执行,所以直接调用
            if (callNow) func.apply(_this, args)
        }
        else {
            timer = setTimeout(function () {
                func.apply(_this, args)
            }, wait);
        }
    }
    return debounced}

4.3 Ajouter une méthode d'événement d'annulation

function debounce(func, wait, immediate) {
    var timer;
    // 检查函数
    if (typeof func !== 'function') {
        throw new TypeError('Expected a function');
    }
    // 保证wait存在
    wait = +wait || 0;

    const debounced = function () {
        var _this = this;
        var args = arguments;

        if (timer) clearTimeout(timer); // 常规流程,间隔内触发时清掉重置定时
        if (immediate) {
            // 如果已经执行过,不再执行
            var callNow = !timer; // 如果不存在定时器,则callNow为true
            timer = setTimeout(function () {
                timer = null; // 为了保证之后的时效性,手动添加timer
            }, wait)
            // 因为不存在timer,证明是首次执行,所以直接调用
            if (callNow) func.apply(_this, args)
        }
        else {
            timer = setTimeout(function () {
                func.apply(_this, args)
            }, wait);
        }
    }

    const cancel = function(){
        clearTimeout(timer);
        timer = null;
    }

    const pending = function(){
        return timer !== undefined;
    }

    debounced.cancel = cancel;
    debounced.pending = pending;
    return debounced}

4.3 Ajouter une méthode d'événement d'annulation

Si vous souhaitez annuler l'événement anti-shake, nous pouvons écrire comme ceci :

rrreee

Regardons l'effet :

Troisième sujet JavaScript : Anti-tremblement

a écrit Même si cette méthode simple anti-tremblement est correcte, elle n'est en effet pas parfaite. Si vous avez des suggestions d'amélioration, veuillez laisser un message dans la zone de commentaire~.

Recommandations d'apprentissage gratuites associées : javascript (vidéo)

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer