const eventHandler = e => {
const keyActions = {
Escape: closeGallery,
ArrowLeft: prevMedia,
ArrowRight: nextMedia
}
if (e.key === 'ArrowLeft') {
prevMedia()
}
if (e.key === 'ArrowRight') {
nextMedia()
}
}
const eventHandler = e => {
const keyActions = {
Escape: closeGallery,
ArrowLeft: prevMedia,
ArrowRight: nextMedia
}
keyActions[e.key]?.()
}
<template>
<div>
<ul>
<li v-for="item in cartItems" :key="item.id">
{{ item.name }} - {{ item.price }} - Quantity: {{ item.quantity }}
</li>
</ul>
<p>Total Price: {{ totalPrice }}</p>
<p>Total Quantity: {{ totalQuantity }}</p>
</div>
</template>
<script>
export default {
data() {
return {
cartItems: [
{ id: 1, name: 'Item 1', price: 10, quantity: 2 },
{ id: 2, name: 'Item 2', price: 15, quantity: 1 },
{ id: 3, name: 'Item 3', price: 20, quantity: 3 }
]
};
},
computed: {
totalPrice() {
return this.cartItems.reduce((total, item) => total + item.price * item.quantity, 0);
},
totalQuantity() {
return this.cartItems.reduce((total, item) => total + item.quantity, 0);
}
}
};
</script>
Object.keys(window).forEach(key => {
if (/^on/.test(key)) {
window.addEventListener(key.slice(2), event => {
console.log(event);
});
}
});
Vývoj software je často o hledání správné rovnováhy mezi:
čistotou kódu vs. praktičností
přehledností vs. flexibilitou
striktními pravidly vs. pragmatickým přístupem
A jak jste správně poznamenal - je to neustálý proces učení a přizpůsobování. Co fungovalo včera, nemusí být nejlepší řešení zítra. A to je v pořádku!
Důležité je:
Dělat informovaná rozhodnutí
Nebát se změny, když je potřeba
Učit se z předchozích zkušeností
Zachovat si zdravý rozum a neupnout se na jeden přístup
Proto je tak důležité mít v týmu otevřenou diskusi o těchto věcech - přesně jako teď! 👍
<!--
https://codepen.io/kevinpowell/pen/OJaBNQE
-->
<div class="grid">
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item offset"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
</div>
<style>
.grid {
margin: 2rem auto;
max-width: 900px;
display: grid;
gap: 1rem;
grid-template-columns: repeat(8, 1fr);
}
.grid-item {
padding: 2rem;
background: lightblue;
border: 4px solid royalblue;
grid-column: span 2;
}
.offset {
grid-column: 2 / span 2;
}
</style>
/*
https://javascript.plainenglish.io/3-powerful-ways-to-share-data-across-browser-tabs-in-javascript-a6a98dffa1a3
*/
// 1. local storage
// Sender
localStorage.setItem('sharedData', JSON.stringify({
message: 'Hello from Tab1!',
timestamp: Date.now()
}));
// Receiver
window.addEventListener('storage', (e) => {
if(e.key === 'sharedData') {
const data = JSON.parse(e.newValue);
console.log('Received data:', data);
}
});
// 2. BroadcastChannel API
// Create a channel (use the same channel name across all tabs)
const channel = new BroadcastChannel('app-channel');
// Send a message
channel.postMessage({
type: 'USER_UPDATE',
payload: { name: 'John' }
});
// Receive messages
channel.onmessage = (e) => {
console.log('Received broadcast:', e.data);
};
// Close the connection
window.onunload = () => channel.close();
// 3.SharedWorker Shared Thread
// shared-worker.js
let ports = [];
onconnect = (e) => {
const port = e.ports[0];
ports.push(port);
port.onmessage = (e) => {
// Broadcast to all connected pages
ports.forEach(p => {
if(p !== port) p.postMessage(e.data);
});
};
};
// Page code
const worker = new SharedWorker('shared-worker.js');
worker.port.start();
// Send a message
worker.port.postMessage('Message from Tab A');
// Receive messages
worker.port.onmessage = (e) => {
console.log('Shared thread message:', e.data);
};
// https://devsmitra.medium.com/javascript-error-handling-just-got-a-whole-lot-easier-meet-the-safe-assignment-operator-c372d892d4ed
// without
async function getData() {
try {
const response = await fetch("https://api.example.com/data");
const json = await response.json();
return validationSchema.parse(json);
} catch (error) {
handleError(error);
}
}
// with
async function getData() {
const [fetchError, response]?= await fetch("https://api.example.com/data");
if (fetchError) return handleFetchError(fetchError);
const [jsonError, json]?= await response.json();
if (jsonError) return handleJsonError(jsonError);
const [validationError, data]?= validationSchema.parse(json);
if (validationError) return handleValidationError(validationError);
return data;
}
// my version - inspired by https://michaelnthiessen.com/stealing-prop-types/
// iconDefault.js
export const iconDefaults = {
size: 'medium',
shape: 'circle',
icon: 'default',
animation: 'none'
};
<!-- Icon.vue -->
<script setup>
import { iconDefaults } from './iconDefaults.js';
const props = defineProps({
size: { type: String, default: iconDefaults.size },
shape: { type: String, default: iconDefaults.shape },
icon: { type: String, default: iconDefaults.icon },
animation: { type: String, default: iconDefaults.animation }
});
</script>
<!-- Panel.vue -->
<script setup>
import Icon from './Icon.vue';
import { iconDefaults } from './iconDefaults.js';
import { computed } from 'vue';
const props = defineProps({
heading: String,
withIcons: Boolean,
iconConfig: {
type: Object,
default: () => ({ ...iconDefaults })
}
});
const finalIconConfig = computed(() => {
return { ...iconDefaults, ...props.iconConfig };
});
</script>