Smokey Dawson
Smokey Dawson

Reputation: 9240

Issue with method not returning values in interpolation nuxjs/vue

In my nuxtjs app static folder I have a file called data.json

in my component I use this data like so

<script>
import data from '~/static/data.json';
export default {
    data ({ params }) {
        return {
            data
        }
    }
}
</script>

now I have a method that will basically take values from that data and create a little counting up animation like so

methods: {
    countUp(value) {
        for (let i = 0; i <= value; i++) {
            setTimeout(() => {
                return i;
            }, 100);
        }
    }
}

and in my template I am calling it like so

<template>
    <div>
       <p>{{countUp(data.number)}}</p>
    </div>
</template>

now the expected result is for the number to quickly change from 0 to the value but nothing is being printed on the dom if I inspect the html element its empty??

What am I doing wrong??

Upvotes: 0

Views: 388

Answers (1)

Decade Moon
Decade Moon

Reputation: 34306

setTimeout doesn't work the way you think it does:

  • You can't return a value from inside the callback function; nothing is being returned from the countUp method.
  • The call to setTimeout doesn't block, meaning it will return immediately after being called and the callback function passed to it is scheduled for execution asynchronously after the timeout has passed. So every setTimeout call in the for loop will be executed all at once after 100 ms instead of staggered.

You will need to store the current counter value as data on the component so Vue knows to rerender when its value is changed.

The simplest example I can provide follows, but you might want to encapsulate the logic in a separate reusable component.

const value = 50

new Vue({
  el: '#app',

  data: {
    counter: 0,
  },

  methods: {
    countUp() {
      const interval = setInterval(() => {
        this.counter++
        
        if (this.counter >= value) {
          clearInterval(interval)
        }
      }, 100)
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <button @click="countUp">Count Up</button>
  {{ counter }}
</div>

Upvotes: 1

Related Questions