Запуск приложения Nuxt «Не удается прочитать свойства неопределенных», когда дочерний компонент отображается с помощью карусели с помощью щелчка

#javascript #vuejs2 #nuxt.js #flickity

Вопрос:

Я пытаюсь связать свои собственные пользовательские кнопки с вращающейся каруселью в приложении nuxt. Мой родительский компонент установил для prop значение direction по умолчанию left .

 <CarouselBase class="w-screen carousel" :direction="direction">
  <items/>
</CarouselBase>

data() {
  return {
    direction: 'left',  
  },
 

Это код для моего компонента карусели.

 <template>
    <ClientOnly>
        <Flickity
            ref="flickity"
            :key="keyIncrementer"
            class="carousel"
            :class="{ 'carousel--active': active }"
            :options="computedOptions"
        >
            <slot />
        </Flickity>
    </ClientOnly>
</template>

<script>

export default {
    name: 'BaseCarousel',
    props: {
        direction: {
            type: String,
            default: '',
        },
    },
    mounted() {
        if (this.direction === 'right') {
            this.$refs.flickity.next()
        } else if (this.direction === 'left') {
            this.$refs.flickity.previous()
        }
    },
    
}
 

У меня есть этот файл vue-flickity.js в папке плагинов

 import Vue from 'vue'
import Flickity from 'vue-flickity'

Vue.component('Flickity', Flickity)
 

Я получил это сообщение об ошибке =>

 Cannot read properties of undefined (reading 'previous')
 

Я не знаю, как это исправить…

Комментарии:

1. Почему бы вам не попробовать импортировать Flickity из ‘vue-flickity’ прямо в свой компонент вместо плагина и добавить его в свойство «компоненты»? Потому что до сих пор похоже, что Flickity по какой-то причине не извлекается из плагина.

2. Что вы на самом деле пытаетесь здесь сделать? Проведите ползунком по mounted() экрану ? Не следует ли вам использовать метод с a @click , как в документах? Какой смысл скользить напрямую, когда компонент все равно смонтирован?

3. @StasParshin это не работает, потому что пакет не обрабатывает SSR и просто вылетает. Мы выяснили это в одном из предыдущих вопросов автора.

4. Я не хочу сразу прокручивать ползунок на монтируемом, но я инициализировал его «влево» вместо пустой строки ( «» ), чтобы увидеть, что происходит, когда реквизит «слева», по очень простой причине, по которой сейчас я не знаю, как сделать повторное вращение карусели, когда реквизит меняет значение. В любом случае, теперь я только что попробовал использовать @click, как в документах, и получаю то же сообщение об ошибке.

5. На самом деле вам не нужно ничего инициализировать здесь. Внутреннее состояние карусели будет обрабатывать previous next шаги и для вас. Вам не нужно заставлять его перерисовывать ни то, ни другое. Вы можете использовать свои Vue devtools, настроить элемент $vm0 и вручную переключить его, он будет правильно перемещаться. Можете ли вы отредактировать свой вопрос с помощью того, что вы пробовали до сих пор?

Ответ №1:

flickity Ссылка на шаблон еще не доступна в mounted крючке, как <Flickity> показано в следующем цикле.

Дождитесь следующего цикла отрисовки с $nextTick() обратным вызовом, прежде чем обращаться к ссылке шаблона в mounted() :

 export default {
  async mounted() {
    // wait until next render cycle for refs to be available
    await this.$nextTick()

    if (this.direction === 'right') {
      this.$refs.flickity.next()
    } else if (this.direction === 'left') {
      this.$refs.flickity.previous()
    }
  },
}
 

ДЕМОНСТРАЦИЯ

Комментарии:

1. Я попробовал вашу демонстрационную версию, ваша карусель использует кнопки, предоставляемые flickity. Я прокомментировал весь асинхронный крючок с открытым ртом, и он работал так же. Похоже, что направляющая опора ничего не делает.

2. @Maxime не уверен, где вы видели, что вам все равно нужна направляющая опора. Как я уже говорил вам, просто используйте кнопки с @click событием, как в документации.

3. @kissu Я сделал, как в документации, избавился от опоры направления.

4. @Maxime Да. Этот вопрос был о том, почему this.$refs.flickity не был определен в mounted крючке. Не об использовании пользовательских кнопок или direction реквизита, которые находятся в отдельных ваших вопросах.

Ответ №2:

Наличие карусели в качестве компонента, подобного этому

 <template>
  <ClientOnly>
    <Flickity ref="flickity">
      <slot />
    </Flickity>
  </ClientOnly>
</template>

export default {
    name: 'BaseCarousel',
}
 

и использую его в своем указателе с помощью моих собственных пользовательских кнопок

 <template>
  <CarouselBase ref="flickityIndex">
    <items for the carousel/>
  </CarouselBase>
  <button @click="previous">Custom Previous Button</button>
  <button @click="next">Custom Next Button</button>
</template>

export default {
     methods: {
    next() {
      this.$refs.flickityIndex.$refs.flickity.next();
    },
    
    previous() {
      this.$refs.flickityIndex.$refs.flickity.previous();
    }
  }
}
 

При следующем или предыдущем вызове необходимо связаться flickity и с тем, и с другим $refs .