B
B
brave_guide2021-05-11 20:06:49
Vue.js
brave_guide, 2021-05-11 20:06:49

Why do routing errors occur?

There is a block component with product cards, which accepts an array of products in props, respectively, and generates product cards using 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>

The "item" structure is something like this:

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

Due to the fact that there may not be product images, you have to check for their presence, and if the check is passed, iterate through the images through v-for and render them into the product card. Also in the product card there is a "router-link" with dynamic parameters, depending on the displayed "item". The product card code looks like this:

<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>

As planned, the images in the card switch automatically at a certain interval, as a result, the following code is implemented (probably because of it the problem is):

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()
    }
  }
}

I hope the code is clear, and there is no need to go into much detail, but from the main points:
For each "item" a check is performed for the presence of image variants. If there are any, a method is launched for them, which alternately changes the large image from the options of the small image, and assigns the active class to the small one. Accordingly, each "item" has its own animation.

The problem is that when you click on the "router-link" link with the id parameter in the product card, the application displays the desired page, but class assignment errors are thrown into the console. That is, when you go to the detailed product description page, the components and product cards are still active, and each of its methods of changing the image is executed, although the page is no longer active. Reloading the page solves the problem.

I have 2 options:
1. Incorrectly implemented class assignment logic
2. Incorrect use of router

Here is the router code:

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 }
  }
})

And, accordingly, in 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')

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dima Pautov, 2021-05-11
@brave_guide

// CatalogItem.vue

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

Ps All events you hang with addEventListener , all timers, all socket connections you create, all need to be cleared when the component is destroyed

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question