从父组件重置一个 Vue 计数器组件
Reset a Vue counter component from the parent component
我有一个从 1 计数到 10 的 Vue 计数器。它是作为一个组件实现的。我需要从主应用程序重置计数器。最好的方法是什么?从我的示例中可以看出,watch 方法无法完成工作:
Vue.component('my-counter', {
template: "#counter-vue",
data: function() {
return {
age_now: null
}
},
props: {
age: Number
},
mounted: function() {
this.age_now = this.age;
TweenLite.to(this, 10, { age_now: this.$root.age_end, roundProps: "age_now", ease:Linear.easeNone });
},
watch: {
age(val) {
this.age_now = val;
}
}
});
var app = new Vue({
el: '.container',
data: {
age: 1,
age_end: 10
},
methods: {
reset() {
this.age = 1;
}
}
});
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<script type="text/x-template" id="counter-vue">
<div>
<p>Age: {{age_now}}</p>
</div>
</script>
<div class="container">
<h1>Vue Component Reset</h1>
<my-counter :age="age"></my-counter>
<button @click.prevent="reset">Reset</button>
<p>What's the best way to implement the reset of the component to restart the count up from 1 to 10?</p>
</div>
另见 CodePen:https://codepen.io/MSCAU/pen/OagMJy
首先,my-counter
组件中 age
的观察者永远不会触发,因为您永远不会更改 age
属性的值。如果它初始化为 1
并在点击处理程序中设置为 1
,它不会触发观察者,因为值没有改变。
但其次,在这种情况下,将 reset
方法移动到 my-counter
组件,然后通过 ref
,像这样:
<my-counter ref="counter" :age="age"></my-counter>
<button @click.prevent="$refs.counter.reset">Reset</button>
如果您希望计数器再次递增,您似乎还需要再次调用 TweenLite.to
方法。因此,最好将该逻辑拉入它自己的方法(例如 count
),您可以从 mounted
挂钩和 reset
方法调用该方法。
此外,我注意到 TweenLite.to
方法似乎也在覆盖 age
道具的绑定,直到计数器完成递增。如果您想在 TweenLite.to
方法完成之前重置计数器,您需要存储对返回的补间对象的引用,然后在计数器开始之前调用其 kill
方法。
最后,我发现您在传递给 TweenLite.to
的对象中引用了 this.$root.age_end
。除了在极少数情况下,这被认为是不好的做法,因为现在组件不必要地依赖于始终具有 age_end
属性 的根 Vue 实例,并且它模糊了数据流。由于该值似乎是静态的,您应该将其设置为组件的数据 属性。或者至少将其作为父项的道具传递。
这是一个包含我建议的更改的工作示例:
Vue.component('my-counter', {
template: "#counter-vue",
data: function() {
return {
age_now: null,
age_end: 10,
tween: null,
}
},
props: {
age: Number
},
mounted: function() {
this.age_now = this.age;
this.count();
},
methods: {
count() {
if (this.tween) {
this.tween.kill();
}
this.tween = TweenLite.to(this, 10, {
age_now: this.age_end,
roundProps: "age_now",
ease: Linear.easeNone
});
},
reset() {
this.age_now = 1;
this.count();
}
}
});
var app = new Vue({
el: '.container',
data: {
age: 1,
}
});
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<script type="text/x-template" id="counter-vue">
<div>
<p>Age: {{age_now}}</p>
</div>
</script>
<div class="container">
<h1>Vue Component Reset</h1>
<my-counter ref="counter" :age="age"></my-counter>
<button @click.prevent="$refs.counter.reset">Reset</button>
</div>
我有一个从 1 计数到 10 的 Vue 计数器。它是作为一个组件实现的。我需要从主应用程序重置计数器。最好的方法是什么?从我的示例中可以看出,watch 方法无法完成工作:
Vue.component('my-counter', {
template: "#counter-vue",
data: function() {
return {
age_now: null
}
},
props: {
age: Number
},
mounted: function() {
this.age_now = this.age;
TweenLite.to(this, 10, { age_now: this.$root.age_end, roundProps: "age_now", ease:Linear.easeNone });
},
watch: {
age(val) {
this.age_now = val;
}
}
});
var app = new Vue({
el: '.container',
data: {
age: 1,
age_end: 10
},
methods: {
reset() {
this.age = 1;
}
}
});
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<script type="text/x-template" id="counter-vue">
<div>
<p>Age: {{age_now}}</p>
</div>
</script>
<div class="container">
<h1>Vue Component Reset</h1>
<my-counter :age="age"></my-counter>
<button @click.prevent="reset">Reset</button>
<p>What's the best way to implement the reset of the component to restart the count up from 1 to 10?</p>
</div>
另见 CodePen:https://codepen.io/MSCAU/pen/OagMJy
首先,my-counter
组件中 age
的观察者永远不会触发,因为您永远不会更改 age
属性的值。如果它初始化为 1
并在点击处理程序中设置为 1
,它不会触发观察者,因为值没有改变。
但其次,在这种情况下,将 reset
方法移动到 my-counter
组件,然后通过 ref
,像这样:
<my-counter ref="counter" :age="age"></my-counter>
<button @click.prevent="$refs.counter.reset">Reset</button>
如果您希望计数器再次递增,您似乎还需要再次调用 TweenLite.to
方法。因此,最好将该逻辑拉入它自己的方法(例如 count
),您可以从 mounted
挂钩和 reset
方法调用该方法。
此外,我注意到 TweenLite.to
方法似乎也在覆盖 age
道具的绑定,直到计数器完成递增。如果您想在 TweenLite.to
方法完成之前重置计数器,您需要存储对返回的补间对象的引用,然后在计数器开始之前调用其 kill
方法。
最后,我发现您在传递给 TweenLite.to
的对象中引用了 this.$root.age_end
。除了在极少数情况下,这被认为是不好的做法,因为现在组件不必要地依赖于始终具有 age_end
属性 的根 Vue 实例,并且它模糊了数据流。由于该值似乎是静态的,您应该将其设置为组件的数据 属性。或者至少将其作为父项的道具传递。
这是一个包含我建议的更改的工作示例:
Vue.component('my-counter', {
template: "#counter-vue",
data: function() {
return {
age_now: null,
age_end: 10,
tween: null,
}
},
props: {
age: Number
},
mounted: function() {
this.age_now = this.age;
this.count();
},
methods: {
count() {
if (this.tween) {
this.tween.kill();
}
this.tween = TweenLite.to(this, 10, {
age_now: this.age_end,
roundProps: "age_now",
ease: Linear.easeNone
});
},
reset() {
this.age_now = 1;
this.count();
}
}
});
var app = new Vue({
el: '.container',
data: {
age: 1,
}
});
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<script type="text/x-template" id="counter-vue">
<div>
<p>Age: {{age_now}}</p>
</div>
</script>
<div class="container">
<h1>Vue Component Reset</h1>
<my-counter ref="counter" :age="age"></my-counter>
<button @click.prevent="$refs.counter.reset">Reset</button>
</div>