0

I have got follow Vue-js App:

<html>
    <head>
    <script src="https://cdn.jsdelivr.net/vue/1.0.26/vue.min.js"></script>
        <style>
            .mydiv
            {
                border: 1px black dashed;
                font-size: 2em;
            }
        </style>

    <script>
    var App = null; // it's global because function behind will overwrite it's with Vue App instance
    window.onload = function() 
    {
        new Vue(
        {
              el: '#app',
              data: 
              {
                btntext: "OK"
              },
              methods:
              {
                change: function()
                {
                    this.btntext = "cancel";
                    setTimeout(function() {console.log("test"); this.btntext = "text changed";},1000);
                }
              }

        })  
    }
    </script>
    </head>

    <body>
        <div id="app">
            <div class="mydiv">
                <button v-on:click="change">{{btntext}}</button>
            </div>
        </div>
    </body>
</html>

After running I am getting "test" on console, but button do not change it's text to text changed. Why?

2 Answers 2

1

The function given to setTimeout does not have the same "this" as your Vue. You could use the bind function:

new Vue({
	el: '#app',
	data: {
		btntext: "OK"
	},
	methods: {
		change: function () {
			this.btntext = "cancel";
			setTimeout(function () {
				console.log("test");
				this.btntext = "text changed";
			}.bind(this), 1000);
		}
	}
})  
.mydiv{
  border: 1px black dashed;
  font-size: 2em;
}
<script src="https://cdn.jsdelivr.net/vue/1.0.26/vue.min.js"></script>
<div id="app">
  <div class="mydiv">
    <button v-on:click="change">{{btntext}}</button>
  </div>
</div>

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

4 Comments

.bind(this) will bind this top level function?
Check developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… for an explanatino on bind. Basically you can do: var o = {foo:'bar'}; setTimeout(function(){console.log(this.foo);}.bind(o), 100);
@user1432751 first argument of Function.bind is thisArg, and will change what object this points to. So in the case of this example, it will change this from pointing to global this (== window) to this inside Vue, where your btntext is stored.
How do you do it with ecmascript?
1

You have to understand the context of this keyword. When in setTimeout callback function, this refers to different object that this before it. To solve this issue, you should solve reference to this before the callback or if you're going to use ES2015, you can change function () {...} with arrow function () => {...}, which will automatically save reference to outer this and use it instead of actual this inside the function. But if you're going to use that, make sure it's supported across all your target browsers, or alternatively use a compiler to ES5, most popular of which is Babel.

2 Comments

Something like this? ` change: () => { this.btntext = "cancel"; setTimeout(function() {console.log("test"); this.btntext = "text changed";},1000); } ` ?
No, use arrow function as the function passed to setTimeout, like setTimeout(() => { ... }, 1000)

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.