javascript - 带有 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
,仅供参考。
我可以做些什么来解决我的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-flickity
使用 Vue 3,但该组件是为 Vue 2 构建的。
Flickity
您可以在 Vue 3中创建自己的组件:
Flickity.vue
使用以下模板和脚本创建,它在根元素上应用模板引用,并包含一个接收元素的插槽.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>
声明一个
options
prop,Flickity
稍后我们将其传递给构造函数。<script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ props: { options: Object, } }) </script>
在组件的
mounted
hookFlickity
中,使用"root"
模板 ref 和options
prop进行实例化;在 中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>
添加一个名为
"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>
使用以下类型声明创建
src/flickity.d.ts
(如果使用 VS Code,则必须重新启动 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 }
添加以下
<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>
推荐阅读
- python - Python从地址生成纬度/经度点
- python - 基于SVD实现计算酉矩阵的行列式
- dart - Dart get class property value dynamically
- python - 打印命令行脚本的调用函数
- javascript - 使用嵌套的 forEach 循环推送到数组
- php - PHP CURL DB 更新与从支付网关收到的状态
- sql - 为什么 Azure SQL 不认为下划线出现在空格和“ZZZZZ”之间?
- python - 在python3中,除非另有说明,否则类中的对象是否仅在该类中可用?
- typescript - Typescript 接口不接受带有强制键的动态对象
- python - 通过 Python 取消静音窗口