Taylor Chance
Taylor Chance

Reputation: 121

Cycle animation or active class through Vue js loop

I have already created this effect in an old vanilla js app. I have a series of blocks that have a hover animation, and when there is no hover, the animation cycles block by block in succession.

I have rebuilt the whole app in Vue js, and everything else has been much easier. This is the only part of the app that I am struggling to do the "Vue" way with no dom manipulation. Basically I have a 3 second timeout where the component gets the "active" class, and then the class switches to the next component in the v-for.

Any suggestions?

Upvotes: 0

Views: 353

Answers (1)

skirtle
skirtle

Reputation: 29102

You should just need to represent the relevant state using properties in data. Whenever you feel tempted to manipulate the DOM directly just update some state instead and wire that up to the template accordingly.

Hopefully this demo does what you want:

new Vue({
  el: '#app',
  
  data () {
    return {
      active: 0,
      
      items: [
        'Red',
        'Green',
        'Blue',
        'Yellow'
      ]
    }
  },
  
  mounted () {
    this.startTimer()
  },
  
  destroyed () {
    this.stopTimer()
  },
  
  methods: {
    onMouseEnter (index) {
      this.stopTimer()
      this.active = index
    },
    
    onMouseLeave () {
      this.startTimer()
    },
    
    startTimer () {
      if (this.timerId) {
        return
      }
    
      this.timerId = setInterval(() => {
        this.active = (this.active + 1) % 4
      }, 500)    
    },
    
    stopTimer () {
      clearInterval(this.timerId)
      this.timerId = null
    }
  }
})
ul {
  border: 1px solid #777;
  margin: 0;
  padding: 0;
}

li {
  list-style: none;
  padding: 5px;
}

.active {
  background: #ccf;
}
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>

<div id="app">
  <ul>
    <li
      v-for="(item, index) in items"
      :key="item"
      :class="{ active: active === index }"
      @mouseenter="onMouseEnter(index)"
      @mouseleave="onMouseLeave"
    >
      {{ item }}
    </li>
  </ul>
</div>

Upvotes: 1

Related Questions