带有Vue 3和Typescript的Flickity API



我一直在Vue 3应用程序中使用Flickity,当我使用带有静态单元格的硬编码HTML旋转木马时,它工作得很好。然而,我需要在运行时以编程方式添加单元格,并且我无法使Flickity API正常工作。

我试图遵循append()的例子,但我得到了错误:

flickity.js?1385:72 Bad element for Flickity: .carousel

在运行时在我的检查器中。我试着在这里和这里遵循解决方案,但都没能成功运行。看起来这是由于Flickity库上的TypeScript错误造成的。我还安装了@types/flickity,fyi。

我可以做些什么来修复下面的append逻辑?

<template>
<div class="row">
<div class="col d-block m-auto payment-option">
<flickity ref="carousel" :options="flickityOptions">
</flickity>
</div>
</div>
</template>
<script lang="ts">
import {defineComponent} from "vue";
//import Flickity from 'vue-flickity/src/flickity.vue';
import Flickity from 'flickity'
export default defineComponent({
name: "PageName",
components: {
Flickity
},
data() {
return {
flickityOptions: {
initialIndex: 3,
prevNextButtons: false,
pageDots: true,
wrapAround: true
}
};
},
methods: {
createBankAccountCarousel(flkty: Flickity) {
flkty.append(this.makeFlickityCell())
},
makeFlickityCell() {
const cell = document.createElement('div');
cell.className = 'carousel-cell'
cell.textContent = "Hi"
return cell
}
},
mounted() {
let flkty = new Flickity(this.$refs.carousel)
this.createBankAccountCarousel(flkty)
}
});
</script>

看起来您可能在Vue 3中尝试vue-flickity,但该组件是为Vue 2构建的。

您可以在Vue 3:中创建自己的Flickity组件

  1. 使用以下模板和脚本创建Flickity.vue,该模板和脚本在根元素上应用模板ref,并包含一个用于接收.carousel-cell元素的插槽:

    <template>
    <!-- 👇 template ref -->
    <div ref="root" class="flickity">
    <slot />
    </div>
    </template>
    <script lang="ts">
    import { defineComponent, ref } from 'vue'
    export default defineComponent({
    setup() {
    const root = ref<HTMLElement | null>(null) // reference to template ref named "root"
    return {
    root,
    }
    }
    })
    </script>
    
  2. 声明一个options道具,稍后我们将把它传递给Flickity构造函数。

    <script lang="ts">
    import { defineComponent } from 'vue'
    export default defineComponent({
    props: {
    options: Object,
    }
    })
    </script>
    
  3. 在组件的mounted钩子中,使用"root"模板ref和options道具实例化Flickity;在unmounted中,销毁Flickity实例:

    <script lang="ts">
    import { defineComponent, onMounted, onUnmounted } from 'vue'
    import Flickity from 'flickity'
    export default defineComponent({
    setup(props) {
    let flickity: typeof Flickity | null = null
    onMounted(() => flickity = new Flickity(root.value as HTMLElement, props.options))
    onUnmounted(() => flickity?.destroy())
    }
    })
    </script>
    
  4. 添加一个名为"append"的方法,以允许向转盘添加新元素:

    <script lang="ts">
    import { defineComponent } from 'vue'
    import Flickity from 'flickity'
    export default defineComponent({
    setup() {
    let flickity: typeof Flickity | null = null
    return {
    append(element: HTMLElement) {
    flickity?.append(element)
    flickity?.select(-1)
    }
    }
    }
    })
    </script>
    
  5. 使用以下类型声明创建src/flickity.d.ts(如果使用VS代码,则必须重新启动IDE才能对这些类型进行索引(:

    declare module 'flickity' {
    const Flickity: {
    new (el: string | HTMLElement, options?: Record<string, unknown>): this
    append(element: HTMLElement)
    destroy()
    select(id: string | number)
    }
    export = Flickity
    }
    
  6. 添加以下<style>块,该块引入flickity默认样式,并对将在插槽中接收的.carousel-cell元素进行样式设置:

    <style scoped>
    @import '~flickity/dist/flickity.css';
    .flickity .carousel {
    background: #EEE;
    margin-bottom: 40px;
    }
    /* use ::v-deep to get at slot elements */
    .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;
    }
    </style>
    

示例用法:

<template>
<div class="app">
<flickity ref="flickity" :options="flickityOptions">
<div class="carousel-cell">1</div>
<div class="carousel-cell">2</div>
<div class="carousel-cell">3</div>
</flickity>
<div class="actions">
<button @click="addElement">Append element</button>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import Flickity from './components/Flickity.vue'
export default defineComponent({
name: 'App',
components: {
Flickity
},
data() {
return {
flickityOptions: {
pageDots: true,
wrapAround: true,
}
}
},
methods: {
addElement() {
// 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 = 'Hi'
return cell
}
}
})
</script>
<style scoped>
.app {
display: flex;
flex-direction: column;
justify-content: space-around;
height: 50vh;
}
</style>

演示

相关内容

  • 没有找到相关文章

最新更新