Please help with 'this' confusion

can some kind soul please explain how to use this in a method to refer to the calling element as one would in vanilla JS? i’m not using an arrow function and i know that this refers to the VueJS object (typically called ‘app’). but i am having trouble porting over existing code that expects this to refer to the calling element, to whit:

<button class='blah active' @click='doStuff()'>CLICK</button>
methods: {
  doStuff() {
    this.classList.toggle('active');
  }
},

what i WANT is for each click to simply toggle the class on and off. what i’ll GET is an this is undefined error because this now refers to the Vue object #app. so please explain how i can make this work the way i WANT it to so i can get this conversion finished up. and, if you can, point me to where in the !@#$ docs i can find a clear explanation.

The method receives the event so you can easily access the DOM element with e.currentTarget. If you call it as @click="doStuff() you have to specifically pass it as @click="doStuff($event), otherwise it’s passed automatically when written as @click="doStuff".

That said, the Vue way to do this is to avoid manually manipulating the DOM. You want Vue to be aware of the state, so you want to make use of data.

<div id="app">
  <button @click="doStuff">CLICK</button>
  <button :class="active && 'active'" @click="doStuffBetter">CLICK</button>
</div>
new Vue({
  el: "#app",
  
  data: {
  	active: false
  },
  
  methods: {
  	doStuff(e) {
    	e.currentTarget.classList.toggle('active');
  	},
    
    doStuffBetter () {
    	this.active = !this.active;
    }
  }
})

JSFiddle: https://jsfiddle.net/jamesbrndwgn/0L1oube6/6/

2 Likes

okay. your comment :

the Vue way to do this is to avoid manually manipulating the DOM

goes a VERY long way to helping me make the continuing mental shift. i understand the bind to :class but don’t understand why you have active && 'active'. why declare it twice?

Sorry, I wrote that up quickly. active is the boolean whereas 'active' is the classname. Note the quotes.

Usually I’d write it as: isActive && 'active'

oh! that works? i thought it was supposed to be { active: isActive }

It’ll work for a single class. The style you’ve used is object notation, so multiple classes. Keep in mind, when you bind, such as a :class or :myProp or :bind, it’s evaluating what’s within the quotes.

@JamesThomson i just came back to re-read this post… man. this has to be one of the most useful posts i’ve read on some of the fundamentals of VueJS. dunno why, but so many little things popped out at me that had nothing to do with the main question, but illuminated so many other little things for me.

so, thank you. i really appreciate the time you take with your answers.

2 Likes

Happy I could help you out :slight_smile: