Сбросить компонент счетчика Vue из родительского компонента - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть счетчик Vue, который считает от 1 до 10. Он реализован как компонент.Мне нужно сбросить счетчик из основного приложения.Какой лучший способ сделать это?Как вы можете видеть из моего примера, метод 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

1 Ответ

0 голосов
/ 16 ноября 2018

Прежде всего, ваш наблюдатель для age в компоненте my-counter никогда не срабатывает, потому что вы никогда не меняете значение пропеллера 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 до запуска счетчика.

Наконец, я вижу, что вы ссылаетесь на this.$root.age_end в объекте, переданном TweenLite.to. За исключением редких случаев, это считается плохой практикой, так как теперь компонент без необходимости зависит от корневого экземпляра Vue, всегда имеющего свойство age_end, и скрывает поток данных. Поскольку это значение выглядит статическим, вы должны просто установить его как свойство данных компонента. Или, по крайней мере, передать это как опору от родителя.

Вот рабочий пример с моими предлагаемыми изменениями:

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>
...