0

我的 Vue 3 Typescript 应用程序中的 Flickity 轮播正在运行时通过 for 循环动态填充幻灯片。

问题:

错误视频 添加到我的轮播中的最后一张幻灯片是唯一显示的幻灯片,当我尝试向左或向右拖动幻灯片时,我的拖动被忽略。对幻灯片导航按钮或页面点的点击会被注册并导致触发幻灯片更改回调,但幻灯片本身永远不会对任何这些点击进行动画/移动/反应。例如:如果我的 Flickity 轮播包含显示“1”和“2”的幻灯片,则幻灯片“2”(最后添加的幻灯片)将始终可见,并且根本不会响应导航按钮/页面点的单击或拖动。

它变得非常奇怪的地方:

当我在 chrome 中打开检查器时,Flickity 轮播立即开始显示独特的可滚动幻灯片。如果我在到达包含轮播的页面后关闭检查器,也会发生同样的事情;它“修复”了这个错误。

我试过的:

我认为检查器的打开或关闭可能会导致 Flickity 的某种内部重新加载调用,所以我尝试在添加所有幻灯片后故意重新加载轮播,但这对错误没有影响。当我在 Chrome 中打开/关闭检查器同时渲染轮播时,会发生一些独特的事情,这使得最后一张幻灯片从始终可见而“脱离”。

代码Page.vue

<template>
<div class="card" v-show="showAccountPicker">
  <h3 class="card-header text-center">Choose Bank Account</h3>
  <div class="card-body text-center">
    <div class="row">
      <div class="col d-block m-auto">
        <flickity ref="flickity" @init="onInit" :options="flickityOptions">
        </flickity>
      </div>
    </div>
  </div>
</div>
<script lang="ts">
import {defineComponent} from "vue";
import Flickity from "./widgets/Flickity.vue";

const axios = require("axios").default;
let bankAccounts = new Set<FundingSource>()

export default defineComponent({
  name: "BankEntryPage",
  components: {
    SpringSpinner,
    Flickity
  },
  data() {
    return {
      flickityOptions: {
        initialIndex: 1,
        prevNextButtons: true,
        pageDots: true,
        wrapAround: false,
      }
    };
  },
  methods: {
    configureBankAccountCarousel(bankAccounts: Set<FundingSource>) {
      let that = this
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      for (let account of bankAccounts) {
        //last added cell is stuck focused by the carousel no matter what clicking/dragging occurs
        (that.$refs.flickity as any).append(that.makeFlickityCell(account))
      }
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (that.$refs.flickity as any).reloadCells() //Doesn't do anything to fix the bug
    },
    makeFlickityCell(bankAccount: FundingSource) {
      const cell = document.createElement('div')
      cell.className = 'carousel-cell'
      cell.textContent = bankAccount.name + "\n" + bankAccount.bankAccountType
      return cell
    },
  },
  mounted() {
    let script = document.createElement("script")
    script.src = "https://cdn.dwolla.com/1/dwolla.js"
    document.head.appendChild(script)

    //Event listener for Flickity carousel
    this.$nextTick(() => {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (this.$refs.flickity as any).on('change', (index: number) => {
        console.log('Slide changed to index ' + index)
      })
    })
  },
  created(){
    this.configureBankAccountCarousel(bankAccounts)
  }
});
</script>

Flickity.vue

<template>
  <div ref="root" class="flickity">
    <slot />
  </div>
</template>

<script lang="ts">
import { defineComponent, onMounted, onUnmounted, ref } from 'vue'
import Flickity from 'flickity'

export default defineComponent({
  props: {
    options: Object,
  },
  setup(props) {
    let flickity: typeof Flickity | null = null
    const root = ref<HTMLElement | null>(null)

    onMounted(() => flickity = new Flickity(root.value as HTMLElement, props.options))
    onUnmounted(() => flickity?.destroy())

    return {
      root,
      append(element: HTMLElement) {
        flickity?.append(element);
        flickity?.select(-1)
      },
      on(eventName: string, listener: () => void) {
        flickity?.on(eventName, listener)
      },
      reloadCells(){
        flickity?.reloadCells()
      }
    }
  },
})
</script>

<style>
@import '~flickity/dist/flickity.css';

.carousel-cell {
  width: 100%;
  height: 200px;
  margin-right: 10px;
  background: #383838;
  border-radius: 5px;
  counter-increment: gallery-cell;
}

/* cell number */
.carousel-cell:before {
  display: block;
  text-align: center;
  /*content: counter(gallery-cell);*/
  line-height: 200px;
  font-size: 80px;
  color: white;
}

/* smaller, dark, rounded square */
.flickity-prev-next-button {
  width: 30px;
  height: 30px;
  border-radius: 5px;
  background: #333;
}
.flickity-prev-next-button:hover {
  background: #248742;
}
/* arrow color */
.flickity-prev-next-button .arrow {
  fill: white;
}
.flickity-prev-next-button.no-svg {
  color: white;
}
/* position outside */
.flickity-prev-next-button.previous {
  left: -5px;
}
.flickity-prev-next-button.next {
  right: -5px;
}

/* white circles */
.flickity-page-dots .dot {
  width: 12px;
  height: 12px;
  opacity: 1;
  background: transparent;
  border: 1px solid white;
}

/* fill-in selected dot */
.flickity-page-dots .dot.is-selected {
  background: white;
}

/* Enable carousel to be keyboard focused & navigated */
/*.flickity-enabled:focus .flickity-viewport {
  outline: thin dotted;
  outline: 5px auto -webkit-focus-ring-color;
}*/
</style>

flickity.d.ts

interface IFlickity {
    new (el: string | HTMLElement, options?: Record<string, unknown>): this;
    append(element: HTMLElement);
    destroy();
    select(id: string | number);
    on(eventName: string, listener: () => void);
    reloadCells();
}

declare module 'flickity' {
    const Flickity: IFlickity;
    export = Flickity;
}
4

0 回答 0