Flickity Events + Vue3 + TypeScript:错误 - this$refs.flickity.on 不是一个函数

Flickity Events + Vue3 + TypeScript: Error - this$refs.flickity.on is not a function

我已经根据接受的答案 .

创建了一个自定义 Flickity.vue 对象以支持 Vue 3 和 TypeScript

然而,当我尝试在我的 flickity 传送带上监听事件时,我被控制台中的运行时类型错误所困扰:this$refs.flickity.on is not a function

是什么导致我目前的方法失败?

DisplayPage.vue

<template>
    <div class="row">
      <div class="col d-block m-auto">
        <flickity ref="flickity" @init="onInit" :options="flickityOptions">
        </flickity>
      </div>
    </div>
</template>

<script lang="ts">
import {defineComponent} from "vue";
import Flickity from "./widgets/Flickity.vue";

export default defineComponent({
  components: {
    Flickity
  },
  data() {
    return {
      flickityOptions: {
        initialIndex: 1,
        prevNextButtons: true,
        pageDots: true,
        wrapAround: false,
      }
    };
  },
  methods: {
    configureBankAccountCarousel() {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (this.$refs.flickity as any).append(this.makeFlickityCell())
    },
    makeFlickityCell() {
      const cell = document.createElement('div')
      cell.className = 'carousel-cell'
      cell.textContent = "Bank Acct"
    }
  },
  mounted() {
    this.configureBankAccountCarousel();
    this.configureBankAccountCarousel();

    this.$nextTick(() => {
      // EVENTS
      (this.$refs.flickity as any).on('ready', function () { //Type ERROR here
        console.log('Flickity is ready!')
      })
    })
  },
});
</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)
      }
    }
  },
})
</script>

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

.flickity .carousel {
  background: #EEE;
  margin-bottom: 40px;
}
.flickity::v-deep .carousel-cell {
  height: 200px;
  width: 25%;
  margin: 0 10px;
  background: #6C6;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
}
.carousel-cell {
  background-color: #248742;
  width: 300px; /* full width */
  height: 160px; /* height of carousel */
  margin-right: 10px;
}

/* position dots in carousel */
.flickity-page-dots {
  bottom: 0px;
}
/* white circles */
.flickity-page-dots .dot {
  width: 12px;
  height: 12px;
  opacity: 1;
  background: white;
  border: 2px solid white;
}
/* fill-in selected dot */
.sr-flickity-page-dots .dot.is-selected {
  background: white;
}

/* no circle */
.flickity-button {
  background: transparent;
}
/* big previous & next buttons */
.flickity-prev-next-button {
  width: 100px;
  height: 100px;
}
/* icon color */
.flickity-button-icon {
  fill: white;
}
/* hide disabled button */
.flickity-button:disabled {
  display: none;
}
</style>

flickity.d.ts

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

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

this.$refs.flickityFlickity.vue 组件,而不是基础 flickity 实例。您的 Flickity.vue 组件没有 on() 方法,这导致了您观察到的错误。

您可以通过 Flickity.vue 中的组件方法公开 flickity 实例的 on() 方法:

// Flickity.vue
export default  defineComponent({
  setup() {
    return {
      on(eventName: string, listener: () => void) {
        flickity?.on(eventName, listener)
      }
    }
  }
})

并更新类型声明以添加 on():

// flickity.d.ts
interface IFlickity {
    //...
    on(eventName: string, listener: () => void)
}

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

demo