Vue JS - 鼠标离开时的清除间隔
Vue JS - Clear Interval on mouseleave
我目前正在通过视频课程学习 VueJS。我正在做关于指令的练习,但有点忘乎所以了。
无论如何,我的目标是通过将鼠标悬停在 "Disco Time" 按钮上来获得 "disco effect"。这很好用,但我也想在离开按钮时清除间隔。
我尝试了几件事(例如,在另一种方法中调用 clear interval),我很确定当前的解决方案不是一个好的解决方案,但据我所知,它至少应该有效。
你能告诉我为什么它不起作用以及它是如何工作的吗?我也会对更好的解决方案感兴趣(但使用指令,因为这是我的目标)。
感谢帮助菜鸟(:
<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>
每次调用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,
}
},
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>
您当前的方法不起作用的原因是 disco() 中的 myDisco 变量的范围仅限于该函数,因此当您再次调用它以尝试清除间隔时,您会得到一个新的空 myDisco包含间隔 ID 的那个。
解决这个问题的一个简单方法是将间隔 ID 本身放在 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>
我目前正在通过视频课程学习 VueJS。我正在做关于指令的练习,但有点忘乎所以了。 无论如何,我的目标是通过将鼠标悬停在 "Disco Time" 按钮上来获得 "disco effect"。这很好用,但我也想在离开按钮时清除间隔。 我尝试了几件事(例如,在另一种方法中调用 clear interval),我很确定当前的解决方案不是一个好的解决方案,但据我所知,它至少应该有效。 你能告诉我为什么它不起作用以及它是如何工作的吗?我也会对更好的解决方案感兴趣(但使用指令,因为这是我的目标)。
感谢帮助菜鸟(:
<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>
每次调用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,
}
},
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>
您当前的方法不起作用的原因是 disco() 中的 myDisco 变量的范围仅限于该函数,因此当您再次调用它以尝试清除间隔时,您会得到一个新的空 myDisco包含间隔 ID 的那个。
解决这个问题的一个简单方法是将间隔 ID 本身放在 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>