Vue JS - Очистить интервал при отпускании мыши - PullRequest
0 голосов
/ 21 февраля 2019

В настоящее время я изучаю VueJS с помощью видео курса.Я делал упражнения по директивам, но немного увлекся.В любом случае, моя цель - получить «эффект диско» при наведении курсора на кнопку «Disco Time».Это прекрасно работает, но я также хочу очистить интервал, когда вы выходите из кнопки.Я перепробовал несколько вещей (например, вызов четкого интервала в другом методе), и я почти уверен, что текущее решение не очень хорошее, но, насколько я понимаю, оно должно работать, по крайней мере.Можете ли вы сказать мне, почему это не работает и как это будет работать?Я также был бы заинтересован в более хороших решениях (но с использованием директивы, поскольку это было моей целью).

Спасибо за помощь новичку (:

<script>
    export default {
        data() {
            return {
              showing: false,
              color: 'lightgreen',
              stopIt: false,
              stopItt: false,
            }
        },
        directives: {
            'myEvent': {
                bind(el, binding) {
                    const type = binding.arg
                    const fn = binding.value
                    el.addEventListener(binding.arg, binding.value)
                }
            }
        },
        methods: {
            change() {
                this.showing = !this.showing;
                this.color == 'lightgreen' ? this.color = 'lightblue' : this.color = 'lightgreen';
            },

            disco() {
                if (this.stopIt == false) {
                    var myDisco = setInterval(() => {
                    this.color == 'lightgreen' ? this.color = 'lightcoral' : this.color = 'lightgreen'
                  }, 100)
                }
                else if (this.stopIt == true) {
                    setTimeout(() => {
                    clearInterval(myDisco)}, 1000)
                }
            },
            stopDisco() {
                  this.stopIt = true
                  //this.stopItt = true
                  this.disco();
            },
      }
}
</script>
<template>
    <div class="container">
        <div class="row">
            <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3">
                <div :style="{color: color}">
                  <h1>Directives Exercise</h1>
                </div>
                <button v-myEvent:click="change" class="btn btn-primary">Show me!</button>
                <button v-myEvent:mouseover="disco" v-myEvent:mouseleave="stopDisco" class="btn btn-primary">Disco Time!</button>
                <p v-if="showing">
                  Now you see me!
                </p>
                <p>
                  {{ stopIt }}, {{ stopItt }}
                </p>
            </div>
        </div>
    </div>
</template>

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Причина, по которой ваш текущий подход не работает, заключается в том, что переменная myDisco в disco () ограничена этой функцией, поэтому, когда вы вызываете ее снова, чтобы попытаться очистить интервал, вы получаете новое пустое myDisco вместоодин, содержащий идентификатор интервала.

Один простой способ исправить это - просто поместить сам идентификатор интервала в data () вместо отдельного логического значения stopIt:

new Vue({
  el: '.container',
  data() {
    return {
      myDisco: undefined,
      color: 'lightgreen',
    }
  },
  directives: {
    'myEvent': {
      bind(el, binding) {
        el.addEventListener(binding.arg, binding.value)
      }
    }
  },
  methods: {
    disco() {
      this.stopDisco(); // just in case there's any chance of calling disco() twice in a row...
      this.myDisco = setInterval(() => {
        this.color == 'lightgreen' ? this.color = 'lightcoral' : this.color = 'lightgreen';
      }, 100)
    },
    stopDisco() {
      clearInterval(this.myDisco); // will be a harmless no-op if myDisco is false
      this.myDisco = undefined; // not strictly necessary, but just to be tidy
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div class="container">
  <div :style="{color: color}">
    <h1>Directives Exercise</h1>
  </div>
  <button v-my-event:mouseover="disco" v-my-event:mouseleave="stopDisco" class="btn btn-primary">Disco Time!</button>
  
  <div>Interval ID: {{myDisco}}</div>
</div>
0 голосов
/ 21 февраля 2019

Каждый раз, когда вы звоните disco, myDisco - это другая переменная.Вы не можете очистить старый таким образом.Вместо этого пусть обратный вызов очищается сам по себе:

disco() {
  this.stopIt = false;
  const myDisco = setInterval(() => {
    this.color == 'lightgreen' ? this.color = 'lightcoral' : this.color = 'lightgreen';
    if (this.stopIt) {
      clearInterval(myDisco);
    }
  }, 100)
},
stopDisco() {
  this.stopIt = true
},

Демонстрационный исполняемый фрагмент ниже.

new Vue({
  el: '.container',
  data() {
    return {
      showing: false,
      color: 'lightgreen',
      stopIt: false,
      stopItt: false,
    }
  },
  directives: {
    'myEvent': {
      bind(el, binding) {
        const type = binding.arg
        const fn = binding.value
        el.addEventListener(binding.arg, binding.value)
      }
    }
  },
  methods: {
    change() {
      this.showing = !this.showing;
      this.color == 'lightgreen' ? this.color = 'lightblue' : this.color = 'lightgreen';
    },

    disco() {
      this.stopIt = false;
      const myDisco = setInterval(() => {
        this.color == 'lightgreen' ? this.color = 'lightcoral' : this.color = 'lightgreen';
        if (this.stopIt) {
          clearInterval(myDisco);
        }
      }, 100)
    },
    stopDisco() {
      this.stopIt = true
    },
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div class="container">
  <div class="row">
    <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3">
      <div :style="{color: color}">
        <h1>Directives Exercise</h1>
      </div>
      <button v-my-event:click="change" class="btn btn-primary">Show me!</button>
      <button v-my-event:mouseover="disco" v-my-event:mouseleave="stopDisco" class="btn btn-primary">Disco Time!</button>
      <p v-if="showing">
        Now you see me!
      </p>
      <p>
        {{ stopIt }}, {{ stopItt }}
      </p>
    </div>
  </div>
</div>
...