@brave_guide

Почему возникают ошибки при роутинге?

Есть компонент блока с карточками товара, который принимает в props соответственно массив товаров, и с помощью v-for генерирует карточки товара:

<template>
  <div class="block">
    <Item
      v-for="item in items"
      :key="item.id"
      :item="item"
      :bigImg="item.imgCatalogBig"
      :variantsBig="item.variantsBig"
    />
  </div>
</template>
<script>
import Item from './Item'
export default {
  name: 'Block',
  props: {item: Array},
  components: {
    Item
  }
}
</script>

Структура "item" приблизительно такова:

{
    "id": 1,
    "name": "name",
    "imgCatalogBig": "name-catalog-big.jpg",
    "imgSmall": ["...jpg.","....jpg","....jpg","....jpg"],
    "variantsBig": ["....jpg","....jpg","....jpg","....jpg"],
    "title": "TITLE",
  }

Из-за того, что изображений товара может не быть, приходится выполнять проверку на их наличие, и если проверка пройдена, через v-for перебирать изображения и рендерить их в карточку товара. Также в карточке товара присутствует "router-link" c динамическими параметрами, в зависимости от отображаемого "item". Приблизительно так выглядит код карточки товара:

<article class="catalog__item" @mouseover="stopAnim" @mouseleave="startAnim">
  <div class="catalog__item-img">
    <div class="catalog__item-imgBig">
      <img
        :src="require('@/img/Catalog/'+imgDefault)"
        :alt="item.name"
      >
    </div>
    <div
      v-if="item.imgSmall.length"
      class="catalog__item-variants"
    >
      <div
        v-for="(img, index) in item.imgSmall"
        :key="index"
        :data-id="index+1"
        class="catalog__item-imgSmall"
        @click="changeBigImg(index)"
        ref="arr"
      >
        <img :src="require('@/img/Catalog/'+img)" :alt="index">
      </div>
    </div>
  </div>
  <div class="catalog__item-content">
    <h3 class="catalog__item-title" v-html="item.title"></h3>
    <router-link
      :to="{name: 'Product', params: {id: item.id}}"
      class="catalog__item-btn"
    >Подробнее</router-link>
  </div>
</article>

По задумке изображения в карточке переключаются автоматически с определенным интервалом, как следствие реализован такой код (вероятно из-за него и проблема):

export default {
  name: 'CatalogItem',
  props: { item: Object, bigImg: String, variantsBig: Array },
  data () {
    return {
      imgDefault: this.bigImg,
      idx: null,
      change: null
    }
  },
  methods: {
    changeBigImg (index) {
      this.imgDefault = this.variantsBig[index]
      this.$refs.ar.find(el => el.classList.contains('active')).classList.remove('active')
      this.$refs.ar[index].classList.add('active')
      this.idx = index
    },
    stopAnim () {
      if (this.variantsBig) {
        clearInterval(this.change)
      }
    },
    startAnim () {
      if (this.variantsBig) {
        this.change = setInterval(() => {
          if (this.idx === this.variantsBig.length) {
            this.idx = 0
          }
          this.changeBigImg(this.idx)
          this.idx++
        }, 2000)
      }
    }
  },
  mounted () {
    if (this.variantsBig) {
      this.$refs.ar[0].classList.add('active')
      this.idx = this.$refs.ar.indexOf(this.$refs.ar.find(el => el.classList.contains('active')))
      this.startAnim()
    }
  }
}

Надеюсь код понятен, и сильно вдаваться в подробности не нужно, но из основных моментов:
Для каждого "item" выполняется проверка на наличие вариантов изображений. Если таковы имеются, для них запускается метод, который поочередно из вариантов маленького изображения меняет большое, и присваивает активный класс маленькому. Соответственно, у каждого "item" своя анимация.

Проблема заключается в том, что при нажатии на ссылку "router-link" с параметром id в карточке товара, приложение отображает нужную страницу, но в консоль бьются ошибки присвоения класса. Т.е., при переходе на страницу подробного описания товара компоненты и карточками товара все еще активны, и выполняют каждый свой метод по смене изображения, хотя страница уже не активна. При перезагрузке страницы проблема исчезает.

У меня 2 варианта:
1. Неправильно реализована логика присвоения класса
2. Неправильное использование router

Вот код роутера:

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
 ...,
  {
    path: '/product/:id',
    name: 'Product',
    component: () => import('../views/Product'),
    props: true
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes,
  scrollBehavior (to, from, savedPosition) {
    return { x: 0, y: 0 }
  }
})

И, соответственно, в main.js:

import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')
  • Вопрос задан
  • 109 просмотров
Решения вопроса 1
bootd
@bootd
Гугли и ты откроешь врата знаний!
// CatalogItem.vue

export default {
  beforeDestroy () {
    this.stopAnim();
  }
}


P.s. Все события, что вы вешаете путём addEventListener, все таймеры, все подключения к сокетам, что создаёте, всё нужно очищать при уничтожении компонента
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы