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.flickity
是 Flickity.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;
}
我已经根据接受的答案
然而,当我尝试在我的 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.flickity
是 Flickity.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;
}