Vue.js Media Transformer - Všechny varianty implementace
1. Composable (Vue 3 Composition API)
// composables/useMediaObjects.js
export function useMediaObjects() {
const transformMediaObjects = (productGallery, productVideos) => {
const finalObjects = []
// Photos
if (productGallery) {
finalObjects.push(
...productGallery.map((photo, index) => ({
...photo,
type: 'photo',
rank: index + 1
}))
)
}
// Videos
if (productVideos) {
finalObjects.push(
...productVideos.map((videoUrl, index) => {
const youtubeId = extractYouTubeId(videoUrl)
return {
url: videoUrl,
type: 'video',
rank: finalObjects.length + index + 1,
previewThumb: youtubeId
? `https://img.youtube.com/vi/${youtubeId}/sddefault.jpg`
: null
}
})
)
}
return finalObjects
}
const extractYouTubeId = (url) => {
return url.match(
/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
)?.[1]
}
return {
transformMediaObjects,
extractYouTubeId
}
}
Použití v komponentě:
// Product.vue
<script setup>
import { computed } from 'vue'
import { useMediaObjects } from '@/composables/useMediaObjects'
const props = defineProps(['productGallery', 'product'])
const { transformMediaObjects } = useMediaObjects()
const mediaObjects = computed(() => {
return transformMediaObjects(props.productGallery, props.product?.product_video)
})
</script>
2. JS Třída - Statické metody
// services/MediaTransformer.js
export class MediaTransformer {
static transform(productGallery, productVideos) {
const finalObjects = []
if (productGallery) {
finalObjects.push(
...productGallery.map((photo, index) => ({
...photo,
type: 'photo',
rank: index + 1
}))
)
}
if (productVideos) {
finalObjects.push(
...productVideos.map((videoUrl, index) => {
const youtubeId = this.extractYouTubeId(videoUrl)
return {
url: videoUrl,
type: 'video',
rank: finalObjects.length + index + 1,
previewThumb: youtubeId
? `https://img.youtube.com/vi/${youtubeId}/sddefault.jpg`
: null
}
})
)
}
return finalObjects
}
static extractYouTubeId(url) {
return url.match(
/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
)?.[1]
}
static generateThumbnail(youtubeId, quality = 'sddefault') {
return `https://img.youtube.com/vi/${youtubeId}/${quality}.jpg`
}
}
Použití:
// Product.vue
<script setup>
import { computed } from 'vue'
import { MediaTransformer } from '@/services/MediaTransformer'
const props = defineProps(['productGallery', 'product'])
const mediaObjects = computed(() => {
return MediaTransformer.transform(props.productGallery, props.product?.product_video)
})
</script>
3. JS Třída - Export třídy (instance v komponentě)
// services/MediaTransformer.js
export class MediaTransformer {
constructor(config = {}) {
this.thumbnailQuality = config.thumbnailQuality || 'sddefault'
this.defaultVideoType = config.defaultVideoType || 'video'
}
transform(productGallery, productVideos) {
const finalObjects = []
if (productGallery) {
finalObjects.push(
...productGallery.map((photo, index) => ({
...photo,
type: 'photo',
rank: index + 1
}))
)
}
if (productVideos) {
finalObjects.push(
...productVideos.map((videoUrl, index) => {
const youtubeId = this.extractYouTubeId(videoUrl)
return {
url: videoUrl,
type: this.defaultVideoType,
rank: finalObjects.length + index + 1,
previewThumb: youtubeId
? `https://img.youtube.com/vi/${youtubeId}/${this.thumbnailQuality}.jpg`
: null
}
})
)
}
return finalObjects
}
extractYouTubeId(url) {
return url.match(
/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
)?.[1]
}
setConfig(newConfig) {
Object.assign(this, newConfig)
return this
}
}
Použití:
// Product.vue
<script setup>
import { computed, ref } from 'vue'
import { MediaTransformer } from '@/services/MediaTransformer'
const props = defineProps(['productGallery', 'product'])
const mediaTransformer = ref(new MediaTransformer({ thumbnailQuality: 'hqdefault' }))
const mediaObjects = computed(() => {
return mediaTransformer.value.transform(props.productGallery, props.product?.product_video)
})
</script>
4. JS Třída - Export instance (singleton)
// services/MediaTransformer.js
class MediaTransformer {
constructor(config = {}) {
this.thumbnailQuality = config.thumbnailQuality || 'sddefault'
}
transform(productGallery, productVideos) {
// stejná implementace jako výše...
}
extractYouTubeId(url) {
// stejná implementace...
}
setConfig(newConfig) {
Object.assign(this, newConfig)
return this
}
}
// Export instance
export const mediaTransformer = new MediaTransformer()
// Případně export obou
export { MediaTransformer }
Použití:
// Product.vue
<script setup>
import { computed } from 'vue'
import { mediaTransformer } from '@/services/MediaTransformer'
const props = defineProps(['productGallery', 'product'])
const mediaObjects = computed(() => {
return mediaTransformer.transform(props.productGallery, props.product?.product_video)
})
// Změna konfigurace kdykoliv:
// mediaTransformer.setConfig({ thumbnailQuality: 'maxresdefault' })
</script>
5. Singleton Pattern
// services/MediaTransformer.js
class MediaTransformer {
static _instance = null
constructor(config = {}) {
if (MediaTransformer._instance) {
return MediaTransformer._instance
}
this.thumbnailQuality = config.thumbnailQuality || 'sddefault'
MediaTransformer._instance = this
}
static getInstance(config = {}) {
if (!this._instance) {
this._instance = new MediaTransformer(config)
}
return this._instance
}
transform(productGallery, productVideos) {
// implementace...
}
extractYouTubeId(url) {
// implementace...
}
}
export default MediaTransformer
Použití:
// Product.vue
<script setup>
import { computed } from 'vue'
import MediaTransformer from '@/services/MediaTransformer'
const props = defineProps(['productGallery', 'product'])
const mediaObjects = computed(() => {
const transformer = MediaTransformer.getInstance({ thumbnailQuality: 'hqdefault' })
return transformer.transform(props.productGallery, props.product?.product_video)
})
</script>
6. Factory Function
// services/MediaTransformer.js
class MediaTransformer {
constructor(config = {}) {
this.thumbnailQuality = config.thumbnailQuality || 'sddefault'
}
transform(productGallery, productVideos) {
// implementace...
}
extractYouTubeId(url) {
// implementace...
}
}
export const createMediaTransformer = (config = {}) => {
return new MediaTransformer(config)
}
// Export i třídy pro pokročilé použití
export { MediaTransformer }
Použití:
// Product.vue
<script setup>
import { computed, ref } from 'vue'
import { createMediaTransformer } from '@/services/MediaTransformer'
const props = defineProps(['productGallery', 'product'])
const mediaTransformer = ref(createMediaTransformer({ thumbnailQuality: 'maxresdefault' }))
const mediaObjects = computed(() => {
return mediaTransformer.value.transform(props.productGallery, props.product?.product_video)
})
</script>
7. Plain Object/Service
// services/mediaService.js
export const mediaService = {
defaultConfig: {
thumbnailQuality: 'sddefault'
},
transform(productGallery, productVideos, config = {}) {
const finalConfig = { ...this.defaultConfig, ...config }
const finalObjects = []
if (productGallery) {
finalObjects.push(
...productGallery.map((photo, index) => ({
...photo,
type: 'photo',
rank: index + 1
}))
)
}
if (productVideos) {
finalObjects.push(
...productVideos.map((videoUrl, index) => {
const youtubeId = this.extractYouTubeId(videoUrl)
return {
url: videoUrl,
type: 'video',
rank: finalObjects.length + index + 1,
previewThumb: youtubeId
? `https://img.youtube.com/vi/${youtubeId}/${finalConfig.thumbnailQuality}.jpg`
: null
}
})
)
}
return finalObjects
},
extractYouTubeId(url) {
return url.match(
/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
)?.[1]
}
}
Použití:
// Product.vue
<script setup>
import { computed } from 'vue'
import { mediaService } from '@/services/mediaService'
const props = defineProps(['productGallery', 'product'])
const mediaObjects = computed(() => {
return mediaService.transform(
props.productGallery,
props.product?.product_video,
{ thumbnailQuality: 'hqdefault' }
)
})
</script>
8. Pure Functions (Helper)
// utils/mediaTransform.js
export const transformMediaObjects = (productGallery, productVideos, config = {}) => {
const { thumbnailQuality = 'sddefault' } = config
const finalObjects = []
if (productGallery) {
finalObjects.push(
...productGallery.map((photo, index) => ({
...photo,
type: 'photo',
rank: index + 1
}))
)
}
if (productVideos) {
finalObjects.push(
...productVideos.map((videoUrl, index) => {
const youtubeId = extractYouTubeId(videoUrl)
return {
url: videoUrl,
type: 'video',
rank: finalObjects.length + index + 1,
previewThumb: youtubeId
? `https://img.youtube.com/vi/${youtubeId}/${thumbnailQuality}.jpg`
: null
}
})
)
}
return finalObjects
}
export const extractYouTubeId = (url) => {
return url.match(
/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
)?.[1]
}
Použití:
// Product.vue
<script setup>
import { computed } from 'vue'
import { transformMediaObjects } from '@/utils/mediaTransform'
const props = defineProps(['productGallery', 'product'])
const mediaObjects = computed(() => {
return transformMediaObjects(
props.productGallery,
props.product?.product_video,
{ thumbnailQuality: 'hqdefault' }
)
})
</script>
Srovnání variant
Varianta |
Výhody |
Nevýhody |
Použití |
Composable |
Vue 3 native, reaktivita, auto-import |
Vue specific |
Vue 3 projekty |
Statické metody |
Jednoduché, žádná konfigurace |
Není flexibilní |
Jednoduché transformace |
Export třídy |
Flexibilní konfigurace |
Musíš vytvářet instance |
Různé konfigurace |
Export instance |
Žádné new , sdílený stav |
Pevná konfigurace |
Jednotná konfigurace |
Singleton |
Jedna instance, lazy loading |
Složitější pattern |
Globální konfigurace |
Factory |
Flexibilní vytváření |
Extra abstrakce |
Komplexní objekty |
Plain Object |
Jednoduché, framework agnostic |
Není OOP |
Malé utility |
Pure Functions |
Nejjednodušší, testovatelné |
Žádná organizace |
Funkcionální přístup |
Doporučení
- Pro jednoduché transformace: Pure Functions nebo Statické metody
- Pro flexibilní konfiguraci: Export třídy nebo Factory
- Pro Vue 3 projekty: Composable
- Pro globální použití: Export instance s
setConfig