Search code examples
javascriptvuejs2vue-componentv-for

Vue JS V-For component reactivity


I have an issue where I can't get a child component to update when new data is passed to it. The data is passing OK but the component doesn't update.

If I change the :key to the object rather than a unique ID it works! But I get a warning error not to use the object as the key, so obviously that is not the way to go?!

 <swiper ref="timelineCarousel" :options="swiperOption">
        <div slot="pagination" class="swiper-pagination kt-margin-b-10"></div>

        <!-- creates swiper slides for each timeline -->
        <swiper-slide
          v-for="timeline in timelines"
          :key="timeline.id + timeline.time"
          class="col-md-3 noSwipe"
        >
          <!-- creates the timeline draggable elements -->
          <timeline
            :id="timeline.id"
            :key="timeline.id + timeline.current_vehicle_reg"
            :hour-to-scroll-to="scrollHour"
            :day-to-scroll-to="scrollDay"
            :month-to-scroll-to="scrollMonth"
            :year-to-scroll-to="scrollYear"
          ></timeline>
        </swiper-slide>
      </swiper>

So when I update this.timeline I can see the data changing in the vue toolsnbut the component doesn't update - unless I use the timeline object as the key!!

I should add that I have added a watcher on the timelines object and that is triggered when I update the data using:

Vue.set(this.timelines, 0, event);

I have no idea what I am doing wrong.


Solution

  • The key is simply a way to give a unique identifier to the list of elements. If you want to make sure that modifying your list of timelines gets the result you expect, it must have a unique key that is not the index of the array.

    // bad
    <swiper-slide
      v-for="(timeline, index) in timelines"
      :key="index"
      class="col-md-3 noSwipe"
    >
    

    Most often, the object's ID can be used for the key. You don't want to use a complex data structure like an object for an ID.

    // good
    <swiper-slide
      v-for="timeline in timelines"
      :key="timeline.id"
      class="col-md-3 noSwipe"
    >
    

    The Vue.js documentation is very good and I recommend reading it yourself. Here is a link to using keys with the v-for directive.

    You don't need the :key property on the children nested inside to fix this issue, just on the element with the v-for.