Vue.js通用Composable实现求助:多组件复用图片处理逻辑
通用Vue组合式函数
useRecipe实现方案 核心思路
让useRecipe兼容两种数据输入场景:
- 组件props传入的单条recipe响应式数据(对应
ItemCard) - 直接从store获取的单条详情响应式数据(对应
ViewRecipeDetail)
通过让组合式函数接受响应式数据源或数据源获取函数作为参数,统一处理不同来源的数据。
具体实现
1. 编写通用useRecipe组合式函数
// composables/useRecipe.js import { ref, onMounted, watch } from 'vue' export function useRecipe(recipeSource) { const currentRecipe = ref(null) // 初始化与更新recipe数据 const updateRecipe = () => { currentRecipe.value = typeof recipeSource === 'function' ? recipeSource() : recipeSource.value } // 首次加载数据 updateRecipe() // 监听数据源变化(如果传入的是响应式对象) if (typeof recipeSource !== 'function') { watch(recipeSource, updateRecipe) } // 生成图片路径的通用方法 const getSrc = (imgName) => { if (!currentRecipe.value || !imgName) return '' return `/assets/recipes/${currentRecipe.value.id}/${imgName}` } // 图片预加载逻辑 const preloadImages = () => { if (!currentRecipe.value?.images) return currentRecipe.value.images.forEach(imgName => { const img = new Image() img.src = getSrc(imgName) }) } // 挂载时预加载,数据变化时重新预加载 onMounted(preloadImages) watch(currentRecipe, preloadImages) return { getSrc, currentRecipe } }
2. 在ItemCard组件中使用
<!-- ItemCard.vue --> <script setup> import { useRecipe } from '@/composables/useRecipe' const props = defineProps({ data: { type: Object, required: true } }) // 直接传入props的响应式数据 const { getSrc } = useRecipe(props.data) </script>
3. 在ViewRecipeDetail组件中使用
<!-- ViewRecipeDetail.vue --> <script setup> import { useRecipe } from '@/composables/useRecipe' import store from '@/store' // 传入获取store数据的函数(适配非响应式store) const { getSrc, currentRecipe } = useRecipe(() => store.state.storeRecipe.data) // 如果使用Pinia等响应式状态管理,可直接传入响应式数据: // const { getSrc, currentRecipe } = useRecipe(store.storeRecipe.data) </script>
方案优势
- 通用性拉满:无需修改组件原有数据逻辑,适配props和store两种数据来源
- 响应式适配:自动监听数据变化,同步更新图片路径与预加载操作
- 逻辑复用彻底:
getSrc和图片预加载逻辑完全抽离,两个组件零重复代码
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

