Resetting CSS animations in Vue is a simple process that can be achieved

Here is a sample list:

var v = new Vue({
  'el' : '#app',
  'data' : {
    'list' : [1,2,3,4,5,6,7,8,9,10]
  },
  
  methods: {
    activateClass($event){
      $event.target.classList.remove('animate');
      void $event.target.offsetWidth;
      $event.target.classList.add('animate');
    },
    changeRandomValue(){
      var randomAmount = Math.round(Math.random() * 12);
      var randomIndex = Math.floor(Math.random() * this.list.length);
      Vue.set(this.list, randomIndex, randomAmount)
    }
  },
  
  mounted(){
    var vm = this;
    setInterval(function(){
      vm.changeRandomValue();
    }, 500);
  }
})
.animate{
  animation: fade 0.5s;
}

@keyframes fade{
  0% { background:blue; }
  100% { background:white; }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js"></script>
<div id="app">
  <ul>
    <li v-for="item in list" v-html="item" @click="activateClass($event)"></li>
  </ul>
</div>

When you run the above code snippet and click on an li element, it will execute the following code:

activateClass($event){
  $event.target.classList.remove('animate');
  void $event.target.offsetWidth;
  $event.target.classList.add('animate');
}

This adds a class to trigger an animation. Cool!

Additionally, there is a changeRandomValue() function that randomly updates an element's value in the list.

How can I call the activateClass method from within the changeRandomValue method?

I've considered using custom events on the element, like:

<li v-for="item in list" v-html="item"
    @click="activateClass($event)"
    @myValueChanged="activateClass($event)"
></li>

However, it seems like this approach isn't supported. I also explored watchers, but they don't seem applicable here.

I can identify the clicked element and retrieve its associated data, but I'm struggling to link the updated data back to its corresponding DOM element.

I'm avoiding class bindings because I need to trigger a reflow. Perhaps there's an easy way to accomplish this in Vue that I'm not aware of.

Answer №1

To easily address this issue, you can utilize class bindings and listen for the animationend event.
Another option is to trigger the same solution programmatically during the mounted event.

new Vue({
  el: '#app',
  data: {
    items: [{
      id: 1,
      highlight: false
    }, {
      id: 2,
      highlight: false
    }]
  },
  mounted() {
    // Demonstrate programmatic highlighting
    setTimeout(() => {
      this.items[1].highlight = true
      setTimeout(() => {
        this.items[1].highlight = true
      }, 1000)
    }, 1000)
  },
  methods: {
    addClass(item) {
      item.highlight = true
    },
    removeClass(item) {
      item.highlight = false
    }
  }
})
p {
  cursor: pointer;
}

.animate {
  animation: fade 0.5s;
}

@keyframes fade {
  0% {
    background: blue;
  }
  100% {
    background: white;
  }
}
<script src="https://unpkg.com/vue@2"></script>

<div id="app">
  <p v-for="item in items" v-bind:class="{ animate: item.highlight }" v-on:click="addClass(item)" v-on:animationend="removeClass(item)">{{ item.id }}</p>
</div>

Answer №2

Following a concise approach similar to the solution provided by @Etheryte:

v-on:click="($event) => $event.target.classList.add('my-class')"
v-on:animationend="($event) => $event.target.classList.remove('my-class')"

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountered a CSS error while trying to compile the project with npm build

When attempting to build the project, I encountered a postcss error. After some debugging, I discovered that the imports below were causing the issue: @import "@material/button/dist/mdc.button.min.css"; /*material text box css*/ @import "@material/float ...

Tips for rearranging a span following an image?

Looking for a solution to rearrange a span element after an image within automatically generated HTML. Sample HTML: <span>closed</span> <img alt="Click to reset" src="xxx" class=""> Currently, the span appears before the img in the cod ...

Switch out the play pause button on an embedded YouTube video player

Is it possible to customize the play/pause button on YouTube iframes using CSS? I have several iframes and would like to change the default red play button. I've attempted the following code: .ytp-large-play-button{ background: url(play.png); } ...

What steps do I need to take in order to successfully implement the v-tabs component in Vuetify.js

I recently implemented the v-tabs component on a webpage. Currently, all three tabs in the example are displaying the same block of data (text): <template> <v-tabs fixed centered> <v-tabs-bar class="cyan" dark> <v-tabs-sl ...

Footer is stubbornly stuck in the middle of the page, refusing to budge despite the

visit the live site here Despite setting the body height:100%, my footer continues to get stuck mid-page on certain pages such as about and contact. I have tried specifying the footer height and using position:fixed, position:absolute, and bottom:0, but n ...

How to utilize Vue.js method to retrieve child prop?

In my Vue.js project, I have created two components. The main component uses a child component called NoteRenderer, which includes a prop named data_exchange. My goal is to update this prop from the main component when a button is clicked. I attempted to a ...

How can props be defined in Vue3 using Typescript?

When using Vue3's defineComponent function, it requires the first generic parameter to be Props. To provide props type using Typescript interface, you can do it like this: export default defineComponent<{ initial?: number }>({ setup(props) { ...

Modify the color of SVG for various sections

I'm looking to create a dynamic hamburger menu that changes color based on different sections of the page. I've experimented with a few approaches, but encountered some issues - the first attempt only works when scrolling down, and the second att ...

Using the ID selector to create a media query

My website is live, and I'm working on making it mobile-friendly. Most of the site works well on mobile, but I'm having trouble centering a jquery lightbox function using media queries. I'm not sure if my syntax is wrong or if there's a ...

Background color applied to row elements in div containers

I've been experimenting with integrating table content into CSS floats, but I'm facing some challenges. My current strategy involves using divs at the "table," "row," and "cell" levels. However, I'm not convinced that this is the most effec ...

Navigate to a specific position with a single click by accessing a class from another Vue component

Clarification of the issue When a user clicks on the login link, the view should automatically scroll down to the login window where they can input their credentials. I know how to achieve this in a single file using document.getElementById('login-w ...

Remove an item from an array in nuxtjs

Whenever I attempt to remove an element from an array, I encounter a peculiar issue. After making three posts and attempting to delete them, the last remaining post is often one that has already been deleted - until I refresh the page. <tr class="b ...

JQuery requests functioning flawlessly on one system while encountering issues on other systems

I've encountered an issue with the code on my admin page. It used to work perfectly fine on my system, but now it seems to have stopped functioning. My client urgently needs to update this page, however, when I attempt to run it, the JQuery requests a ...

Increase or decrease values in an input field using Vue3 when typing

I am looking to implement a feature where users can input numbers that will be subtracted from a fixed total of 100. However, if the user deletes the input, I want the difference to be added back to the total of 100. Despite my attempts, the subtraction wo ...

Styling Material UI components with CSS is a great way to

I'm facing difficulties while working with Material UI components. Currently, I have a Material UI table and I want to center-align the text within it. The standard CSS of Material UI contains an element named MuiTableCell-root-60 which has a text-a ...

What steps should I take to resolve the npm run serve error I'm encountering in the

I recently purchased Vue Material Dashboard Pro (vue-material-dashboard-pro-v1.4.0) and encountered some errors when trying to run npm run serve in the terminal. Can you help me troubleshoot this issue? [email protected] serve /Users/desceliayoshe/v ...

Issue with Sass @use failing to load partial

I'm currently facing an issue while trying to import a sass partial called _variables.scss into my main stylesheet named global.scss. Every time I compile the sass code, I encounter the following error message: Error: Undefined variable. Here is the ...

I am struggling to layer the boxes using z-index

I have been struggling to find a solution to the problem, but nothing seems to be working. My goal is to create a gradient border for a slideshow on my website, similar to the one showcased in this video. I attempted to use the :before pseudo selector in m ...

Adjusting Font Sizes with Bootstrap 4 Media Queries: A Simple Guide

I recently incorporated Bootstrap into my project, but I've encountered an issue with the fixed heading sizes. I'm attempting to modify the font size of my project, especially because the h1 and h2 text appears overly large on mobile devices. Str ...

Tips for creating a dynamic inner DIV that follows the scroll position of an outer DIV without relying on a fixed width

I have created a series of DIV elements to represent a chart. The key element is everything enclosed within the "rightPanel" section in the following code snippet. The "topPanel" section has an absolute position, and its top value (top: 0px) needs to be a ...