3

Run the code and look in the console in your browser. You will see function "formatName()" is called many times. Why? I dont update data of race. But if i change function "amIStarted()" to "return start < 5", then it will be executed 2 times, which is correct. (sorry my english)

https://jsfiddle.net/a496smx2/48/

var stopwatch = new Vue({
    el: "#stopwatch",
  data: {
    time: 1
  },
  created: function() {
    setInterval(function(){
        stopwatch.time++;
    }, 1000);
  }
})

var race = new Vue({
  el: "#race",
  data: {
        startList: [
        {name: "John", start: 3},
        {name: "Mike", start: 7},
        {name: "Gabe", start: 333},
    ],
  },
  methods: {
    amIStarted: function(start) {
        return start < stopwatch.time;
    },
    formatName: function(name) {
        console.log("I was called.")
        return 'Mr. '+name;
    }
  }
});

<div id="stopwatch" ><h4>Time: <span class="gold" >{{time}}</span></h4></div>

<small>Yellow color means the person started</small>

<div id="race" >
  <div v-for="oneStart in startList" :class="{gold : amIStarted(oneStart.start)}" >
    {{formatName(oneStart.name)}} will start when time is more then {{oneStart.start}}
  </div>
  <br><br>
</div>

3 Answers 3

2

You're looking for computed properties instead of methods. They will be optimized so they are run only when a prop it depends on changes. Methods are run every time an update happens, which could be as often as the mouse moves, depending on your application structure and complexity.

Sign up to request clarification or add additional context in comments.

Comments

1

function "formatName()" is called many times. Why?

Because you have added a variable which is continuously changing and checked to add a class :class="{gold : amIStarted(oneStart.start)}" and in each chanve vue reload that part in which function comes and it is calling it again.

var stopwatch = new Vue({
    el: "#stopwatch",
  data: {
    time: 1
  },
  created: function() {
    setInterval(function(){
        stopwatch.time++;
    }, 1000);
  }
})

var race = new Vue({
  el: "#race",
  data: {
        startList: [
        {name: "John", start: 3},
        {name: "Mike", start: 7},
        {name: "Gabe", start: 333},
    ],
  },
  methods: {
    amIStarted: function(start) {
        return start < stopwatch.time;
    },
    formatName: function(name) {
        console.log("I was called.")
        return 'Mr. '+name;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>


<div id="stopwatch" ><h4>Time: <span class="gold" >{{time}}</span></h4></div>

<small>Yellow color means the person started</small>

<div id="race" >
<div>
  <div v-for="oneStart in startList"  >
    {{formatName(oneStart.name)}} will start when time is more then {{oneStart.start}}
  </div>
  <br><br>
  </div>
</div>

Here is the flow

https://vuejs.org/images/data.pngenter image description here

There are many other ways to achieve what you want to do. Please check for those.

Comments

0

Functions or filters embedded in a template will be called every time the template is rendered, so every time you update the time, that function will be run (once per name) as part of the rerender.

So long as your methods have no unwanted side effects, this is generally fine! But in cases where you may have a lot of these going at once and start running into performance issues, you can switch to a computed function.

Computed functions will be called only when the data they depend on changes. You can't pass parameters to a computed function, so rather than handling each individual name separately you'd need to have it modify the full list of names in one go:

var stopwatch = new Vue({
  el: "#stopwatch",
  data: {
    time: 1
  },
  created: function() {
    setInterval(function() {
      stopwatch.time++;
    }, 1000);
  }
})

var race = new Vue({
  el: "#race",
  data: {
    startList: [{
        name: "John",  start: 3
      }, {
        name: "Mike",  start: 7
      }, {
        name: "Gabe",  start: 333
      }
    ]
  },
  computed: {
    formattedList() {
    console.log("Computed function ran");
      let arr = [];
      for (let oneStart of this.startList) {
        arr.push({
          formattedName: 'Mr. ' + oneStart.name,
          start: oneStart.start        
        })
      }
      return arr
    }
  },
  methods: {
    amIStarted: function(start) {
      return start < stopwatch.time;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>

<div id="stopwatch">
  <h4>Time: <span class="gold">{{time}}</span></h4>
</div>

<small>Yellow color means the person started</small>

<div id="race">
  <div v-for="oneStart in formattedList" :class="{gold : amIStarted(oneStart.start)}">
    {{oneStart.formattedName}} will start when time is more then {{oneStart.start}}
  </div>
  <br><br>
</div>

An alternative approach would be to modify the data in a beforeMount() or created() block, but this would only be appropriate if you're certain the input data will not change during the lifespan of the component.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.