2

I am new to Vue.js so I am not sure of the proper way to implement this task correctly. I am looking to build a slider that replaces an image every 4 seconds with a set Interval. Right now it works fine, but I want to use the full power of Vue.js for achieving this goal. I would also like to know how I should terminate the interval when it is unmounted, in order to avoid memory leaks.

    <template>
    <div class="trending col-4">
        <div class="trending-div">
            <h1 class="headline">Trending</h1>
            <div class="trending-articles">
                <div class="trending-articles-names" @click="changeIamge">
                    <p class="trending-articles-names-number activeButton">1</p>
                    <p class="trending-articles-names-articleTitle activeBold">Lorem ipsum </p>
                </div>
                <div class="trending-articles-names" @click="changeIamge">
                    <p class="trending-articles-names-number">2</p>
                    <p class="trending-articles-names-articleTitle">Lorem, ipsum </p>
                </div>
                <div class="trending-articles-names" @click="changeIamge">
                    <p class="trending-articles-names-number">3</p>
                    <p class="trending-articles-names-articleTitle">Lorem ipsum </p>
                </div>
            </div>
            <div class="trending-carousel">
                <div @click="pic" :style="{ backgroundImage: `url(path/to/image)`}" class="trending-carousel-image active"></div>
                <div @click="pic" :style="{ backgroundImage: `url(path/to/image)`}" class="trending-carousel-image"></div>
                <div @click="pic" :style="{ backgroundImage: `url(path/to/image)`}" class="trending-carousel-image"></div>
            </div>
        </div>
    </div>
</template>

<script>
    export default{
        data: function() {
            return {
                counter: 0,

            }
        },
        mounted: function() {
            let carouselImages = document.querySelectorAll('.trending-carousel-image');
            let buttons = document.querySelectorAll('.trending-articles-names-number');
            let title = document.querySelectorAll('.trending-articles-names-articleTitle');
            setInterval(() => {
                carouselImages[this.counter].classList.remove("active")
                buttons[this.counter].classList.remove("activeButton")
                title[this.counter].classList.remove("activeBold")
                if(this.counter === 3) {
                    carouselImages[0].classList.add("active");
                    buttons[0].classList.add("activeButton");
                    title[0].classList.add("activeBold");
                    this.counter = 0;
                }else {
                    carouselImages[this.counter+1].classList.add("active");
                    buttons[this.counter+1].classList.add("activeButton");
                    title[this.counter+1].classList.add("activeBold");
                    this.counter++;
                }
            },4000);
        }
    }
</script>
2
  • Can you please prepare a jsfiddle?
    – Ozan Kurt
    Commented Jul 26, 2019 at 20:14
  • @OzanKurt I tried. It doesn't work well
    – ISAAC
    Commented Jul 26, 2019 at 20:23

1 Answer 1

1

When working with vue you should avoid directly manipulating the dom.

  • If you want to dynamically add / remove classes to an element you can use the object syntax for v-bind:class
  • If you need animations / transitions, you can use Vue transitions (transition / transition-group)
  • If you have many similar elements (e.g. .trending-articles-names in your example code), you can use v-for to create them for you

A very simple carousel thats purely implemented in vue might look like this:
(codepen is available here)

new Vue({
  el: '#root',
  data: function() {
    return {
      articles: [{
        name: "Lorem Ipsum",
        image: "https://via.placeholder.com/300x50.png/FF0000/FFFFFF?text=First"
      }, {
        name: "Lorem Ipsum 2",
        image: "https://via.placeholder.com/300x50.png/00FF00/FFFFFF?text=Second"
      }, {
        name: "Lorem Ipsum 3",
        image: "https://via.placeholder.com/300x50.png/0000FF/FFFFFF?text=Third"
      }],
      activeImage: 0,
      interval: null
    }
  },
  mounted() {
    this.interval = setInterval(this.next, 5000);
  },
  destroyed() {
    // remember to clear the interval once the component is no longer used
    clearInterval(this.interval);
  },
  methods: {
    prev() {
      this.activeImage--;
      if (this.activeImage < 0)
        this.activeImage = this.articles.length - 1;
    },
    next() {
      this.activeImage++;
      if (this.activeImage >= this.articles.length)
        this.activeImage = 0;
    },
    pic(article) {
      console.log("CLICKED ON", article);
    }
  }
});
.carousel {
  overflow: hidden;
  width: 300px;
  display: flex;
}

.carousel img {
  transition: transform 0.5s ease;
}

button {
  margin: 6px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="root">
  <div class="trending col-4">
    <div class="trending-div">
      <div class="trending-articles">
        <div v-for="(article, idx) in articles" :key="idx" class="trending-articles-names" @click="activeImage = idx">{{article.name}}</div>
      </div>
      <div class="carousel">
        <img v-for="(article, idx) in articles" :key="idx" @click="pic(article)" :src="article.image" :style="{transform: `translateX(-${activeImage * 100}%)`}" />
      </div>
      <button type="button" @click="prev">PREV</button>
      <button type="button" @click="next">NEXT</button>
    </div>
  </div>
</div>

I would suggest using a pre-made carousel component for production projects though.
There are several good libaries available for carousels in vue, to name a few:

2
  • Thanks a lot, it is great!
    – ISAAC
    Commented Jul 26, 2019 at 21:29
  • @ISAAC np, glad i could help :) Commented Jul 26, 2019 at 21:29

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.