vue3 手动封装裂图组件
时间: 2025-01-08 10:20:46 浏览: 6
### 封装 Vue3 中的裂图组件
#### 一、创建基础结构
为了构建一个可复用的裂图组件,先建立项目的文件夹结构。假设已经安装好 Vue CLI 并初始化了一个新项目。
```bash
mkdir src/components/FractureImage
touch src/components/FractureImage/FractureImage.vue
```
#### 二、编写 FractureImage 组件代码
在 `FractureImage.vue` 文件内定义模板、样式以及脚本部分来完成基本功能:
```html
<template>
<div class="fracture-image">
<!-- 图片容器 -->
<transition-group name="fragment" tag="ul">
<li v-for="(piece, index) in pieces" :key="index" @click="handleClick(index)">
<img :src="currentSrc[index]" alt="" />
</li>
</transition-group>
</div>
</template>
<script setup>
import { ref } from 'vue';
// 定义属性
const props = defineProps({
images: {
type: Array,
required: true,
},
});
let currentSrc = ref([...props.images]);
let pieces = [...Array(9).keys()]; // 假设分为九宫格形式展示
function handleClick(index) {
const tempIndex = Math.floor(Math.random() * props.images.length);
currentSrc.value.splice(index, 1, props.images[tempIndex]);
}
</script>
<style scoped>
.fracture-image ul {
list-style-type: none;
padding: 0;
}
.fragment-enter-active,
.fragment-leave-active {
transition: all .5s ease-in-out;
}
.fragment-enter-from,
.fragment-leave-to {
opacity: 0;
transform: scale(.8);
}
</style>
```
此段代码实现了简单的点击更换图片片段的效果[^1]。通过传递给组件的一个图像数组,在每次点击某个碎片时随机替换该位置上的图片源链接。
#### 三、引入并使用自定义 Hooks 提升逻辑抽象度
为了让上述逻辑更加模块化易于维护,可以进一步提取出独立于视图层的状态管理逻辑到 hooks 函数中去处理:
```javascript
// src/hooks/useFracture.js
export function useFracture(images) {
let currentIndexes = [];
while (currentIndexes.length < 9) {
var r = Math.floor(Math.random() * images.length);
if (!currentIndexes.includes(r)) currentIndexes.push(r);
}
return () => ({
getCurrentImages: () =>
currentIndexes.map((idx) => ({ ...images[idx], idx })),
updatePieceAtRandomPosition: (positionToUpdate) => {
const newPosition =
currentIndexes[positionToUpdate] === undefined ||
currentIndexes.indexOf(
currentIndexes[positionToUpdate]
) !== positionToUpdate
? Math.floor(Math.random() * images.length)
: currentIndexes[positionToUpdate];
currentIndexes[positionToUpdate] = newPosition;
return newIndex;
}
});
}
```
接着修改原来的 `.vue` 文件以导入这个新的 hook 方法,并调用来替代原有的 inline 实现方式[^2]:
```diff
<script setup>
-import { ref } from 'vue';
+import { useFracture } from '../hooks/useFracture'
// 定义属性
const props = defineProps({
images: {
type: Array,
required: true,
},
});
-let currentSrc = ref([...props.images]);
-let pieces = [...Array(9).keys()];
+const fractureLogic = useFracture(props.images);
-function handleClick(index) {
- const tempIndex = Math.floor(Math.random() * props.images.length);
- currentSrc.value.splice(index, 1, props.images[tempIndex]);
+pieces.forEach((_, i) => fractureLogic.updatePieceAtRandomPosition(i));
+function handleClick(index) {
+ const updatedIdx = fractureLogic.updatePieceAtRandomPosition(index);
+ console.log(`Updated piece at ${index} with image at index ${updatedIdx}`);
}</script>
```
这样不仅提高了代码质量还增强了其灵活性和重用率。
阅读全文