Ontwikkel een Vue.js Component met Geavanceerde State Synchronisatie via Composables
description
Met deze prompt leer je hoe je state efficiënt synchroniseert tussen Vue.js componenten met composables. Dit verbetert de code onderhoudbaarheid en performance, en voorkomt complexe stateproblemen. Het biedt een moderne aanpak die beter schaalbaar is dan traditionele methoden.
prompt
Help me een Vue.js component te ontwikkelen dat geavanceerde state synchronisatie gebruikt via Vue 3 composables. Beschrijf hoe ik gedeelde state kan beheren, updates tussen componenten kan synchroniseren en performance kan optimaliseren met ...
try_prompt
generate_helper
disclaimerOnPageApi
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Hier is een stapsgewijze gids om een Vue 3 component te ontwikkelen die geavanceerde state-synchronisatie gebruikt via composables, gericht op een realtime berichteninterface met gedeelde state, gesynchroniseerde updates en optimale performance:
### 1. Gedeelde state beheren met een composable
Gebruik een Vue 3 composable (bijvoorbeeld `useChatState`) om de gedeelde state centraal te beheren:
```js
// useChatState.js
import { reactive } from 'vue';
export function useChatState() {
const state = reactive({
berichten: [], // lijst van berichten
onlineGebruikers: [] // lijst van online gebruikers
});
// Methoden om state te muteren (bijvoorbeeld berichten toevoegen)
function voegBerichtToe(bericht) {
state.berichten.push(bericht);
}
function updateOnlineGebruikers(users) {
state.onlineGebruikers = users;
}
return {
state,
voegBerichtToe,
updateOnlineGebruikers
};
}
```
### 2. Realtime synchronisatie via WebSocket of een vergelijkbare service
Gebruik een WebSocket-verbinding om de state te synchroniseren zonder vertraging:
```js
// useWebSocket.js
import { ref, onMounted, onUnmounted } from 'vue';
export function useWebSocket(url, onMessageCallback) {
const socket = ref(null);
onMounted(() => {
socket.value = new WebSocket(url);
socket.value.onmessage = (event) => {
const data = JSON.parse(event.data);
onMessageCallback(data);
};
});
onUnmounted(() => {
if (socket.value) {
socket.value.close();
}
});
function send(data) {
if (socket.value && socket.value.readyState === WebSocket.OPEN) {
socket.value.send(JSON.stringify(data));
}
}
return { send, socket: socket.value };
}
```
### 3. Component integratie
Gebruik de composables in je component:
```vue
<template>
<div>
<h2>Realtime Chat</h2>
<div class="berichten">
<div v-for="(bericht, index) in chatState.state.berichten" :key="index">
{{ bericht.gebruiker }}: {{ bericht.text }}
</div>
</div>
<input v-model="nieuwBericht" @keyup.enter="verzendBericht" placeholder="Typ een bericht..." />
<div>
<h3>Online gebruikers:</h3>
<ul>
<li v-for="user in chatState.state.onlineGebruikers" :key="user.id">{{ user.name }}</li>
</ul>
</div>
</div>
</template>
<script>
import { ref } from 'vue';
import { useChatState } from './useChatState';
import { useWebSocket } from './useWebSocket';
export default {
setup() {
const chatState = useChatState();
const nieuwBericht = ref('');
const { send } = useWebSocket('wss://jouw-websocket-url', (data) => {
if (data.type === 'bericht') {
chatState.voegBerichtToe(data.bericht);
} else if (data.type === 'onlineUsers') {
chatState.updateOnlineGebruikers(data.gebruikers);
}
});
function verzendBericht() {
const bericht = {
gebruiker: 'Huidige Gebruiker', // vervang door dynamische naam
text: nieuwBericht.value,
timestamp: Date.now()
};
chatState.voegBerichtToe(bericht);
send({ type: 'bericht', bericht });
nieuwBericht.value = '';
}
return {
chatState,
nieuwBericht,
verzendBericht
};
}
};
</script>
```
### 4. Performance optimalisaties
- **Vermijd onnodige re-renders:** Maak gebruik van `shallowReactive` of `shallowRef` indien nodig, om alleen de benodigde delen te reactiveren.
- **Batch updates:** Verzamel snelle opeenvolgende berichten en verzend ze in één batch, bijvoorbeeld met debounce.
- **Gebruik WebSocket-verbindingen efficiënt:** Houd de verbinding open en minimaliseer herhaald opzetten.
- **Vue's `watch` of `computed`:** Gebruik deze voor geoptimaliseerde reactieve berekeningen en om updates te beperken.
### Samenvatting
- Centraliseer gedeelde state in een composable.
- Gebruik WebSockets voor realtime communicatie, met een composable voor de connectie.
- Synchroniseer berichten en gebruikersstatus direct via WebSocket-berichten.
- Optimaliseer prestaties door het beperken van onnodige re-renders, batching en efficiënte WebSocket-gebruik.
Door deze aanpak krijg je een schaalbare, reactieve en performante Vue.js realtime chatinterface!
provider: deepseek
model: deepseek-chat
Ik zal je helpen een Vue.js 3 component te ontwikkelen met geavanceerde state synchronisatie via composables. Hier is een complete implementatie:
## 1. State Management Composable
```javascript
// composables/useChatState.js
import { ref, computed, watch, readonly } from 'vue'
import { useWebSocket } from './useWebSocket'
export function useChatState() {
const messages = ref([])
const onlineUsers = ref(new Set())
const currentUser = ref(null)
const isLoading = ref(false)
// WebSocket integratie voor realtime updates
const { connect, sendMessage, isConnected } = useWebSocket()
// Gecacheerde computed properties voor performance
const sortedMessages = computed(() => {
return [...messages.value].sort((a, b) =>
new Date(a.timestamp) - new Date(b.timestamp)
)
})
const onlineUsersList = computed(() => {
return Array.from(onlineUsers.value)
})
// State synchronisatie functies
const addMessage = (message) => {
messages.value.push({
...message,
id: Date.now() + Math.random(),
timestamp: new Date().toISOString()
})
// Optimalisatie: behoud alleen laatste 100 berichten
if (messages.value.length > 100) {
messages.value = messages.value.slice(-100)
}
}
const updateOnlineUsers = (users) => {
onlineUsers.value = new Set(users)
}
const setCurrentUser = (user) => {
currentUser.value = user
}
// Real-time synchronisatie via WebSocket
const initializeChat = async (user) => {
isLoading.value = true
setCurrentUser(user)
try {
await connect('wss://your-websocket-server/chat')
// Luister naar realtime updates
watch(isConnected, (connected) => {
if (connected) {
// Synchroniseer initiële state
sendMessage({
type: 'join',
user: user
})
}
})
} catch (error) {
console.error('Chat initialisatie mislukt:', error)
} finally {
isLoading.value = false
}
}
// Exporteer alleen wat nodig is (encapsulatie)
return {
messages: readonly(messages),
sortedMessages: readonly(sortedMessages),
onlineUsers: readonly(onlineUsers),
onlineUsersList: readonly(onlineUsersList),
currentUser: readonly(currentUser),
isLoading: readonly(isLoading),
addMessage,
updateOnlineUsers,
setCurrentUser,
initializeChat
}
}
```
## 2. WebSocket Composable voor Realtime Synchronisatie
```javascript
// composables/useWebSocket.js
import { ref, onUnmounted } from 'vue'
export function useWebSocket() {
const socket = ref(null)
const isConnected = ref(false)
const reconnectAttempts = ref(0)
const maxReconnectAttempts = 5
const messageHandlers = new Set()
const connect = (url) => {
return new Promise((resolve, reject) => {
try {
socket.value = new WebSocket(url)
socket.value.onopen = () => {
isConnected.value = true
reconnectAttempts.value = 0
resolve()
}
socket.value.onmessage = (event) => {
const data = JSON.parse(event.data)
messageHandlers.forEach(handler => handler(data))
}
socket.value.onclose = () => {
isConnected.value = false
attemptReconnect()
}
socket.value.onerror = (error) => {
reject(error)
}
} catch (error) {
reject(error)
}
})
}
const attemptReconnect = () => {
if (reconnectAttempts.value < maxReconnectAttempts) {
setTimeout(() => {
reconnectAttempts.value++
connect(socket.value.url)
}, 1000 * reconnectAttempts.value)
}
}
const sendMessage = (message) => {
if (socket.value && isConnected.value) {
socket.value.send(JSON.stringify(message))
}
}
const onMessage = (handler) => {
messageHandlers.add(handler)
// Cleanup functie retourneren
return () => messageHandlers.delete(handler)
}
onUnmounted(() => {
if (socket.value) {
socket.value.close()
}
})
return {
connect,
sendMessage,
onMessage,
isConnected: readonly(isConnected)
}
}
```
## 3. Hoofd Chat Component
```vue
<!-- components/ChatInterface.vue -->
<template>
<div class="chat-interface">
<!-- Loading state -->
<div v-if="isLoading" class="loading">
Chat initialiseren...
</div>
<!-- Hoofd chat interface -->
<div v-else class="chat-container">
<!-- Online gebruikers sidebar -->
<div class="online-users">
<h3>Online Gebruikers ({{ onlineUsersList.length }})</h3>
<div
v-for="user in onlineUsersList"
:key="user.id"
class="user-item"
:class="{ active: user.id === currentUser?.id }"
>
{{ user.name }}
</div>
</div>
<!-- Chat berichten gebied -->
<div class="chat-messages">
<div class="messages-container">
<div
v-for="message in sortedMessages"
:key="message.id"
class="message"
:class="{ own: message.userId === currentUser?.id }"
>
<div class="message-header">
<strong>{{ message.userName }}</strong>
<span class="timestamp">
{{ formatTime(message.timestamp) }}
</span>
</div>
<div class="message-content">{{ message.content }}</div>
</div>
</div>
<!-- Bericht invoer -->
<div class="message-input">
<input
v-model="newMessage"
@keyup.enter="sendMessage"
placeholder="Typ je bericht..."
:disabled="!isConnected"
/>
<button
@click="sendMessage"
:disabled="!newMessage.trim() || !isConnected"
>
Verstuur
</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { useChatState } from '@/composables/useChatState'
// State management via composable
const {
sortedMessages,
onlineUsersList,
currentUser,
isLoading,
isConnected,
addMessage,
updateOnlineUsers,
initializeChat
} = useChatState()
const newMessage = ref('')
// Component lifecycle
onMounted(() => {
// Initialiseer chat met huidige gebruiker
initializeChat({
id: 'user-123',
name: 'Jouw Naam'
})
})
// Bericht verzenden
const sendMessage = () => {
if (!newMessage.value.trim()) return
addMessage({
content: newMessage.value.trim(),
userId: currentUser.value.id,
userName: currentUser.value.name
})
newMessage.value = ''
}
// Tijd formatting helper
const formatTime = (timestamp) => {
return new Date(timestamp).toLocaleTimeString('nl-NL', {
hour: '2-digit',
minute: '2-digit'
})
}
</script>
<style scoped>
.chat-interface {
height: 100vh;
display: flex;
}
.chat-container {
display: flex;
width: 100%;
height: 100%;
}
.online-users {
width: 250px;
border-right: 1px solid #ddd;
padding: 1rem;
}
.chat-messages {
flex: 1;
display: flex;
flex-direction: column;
}
.messages-container {
flex: 1;
overflow-y: auto;
padding: 1rem;
}
.message {
margin-bottom: 1rem;
padding: 0.5rem;
border-radius: 8px;
}
.message.own {
background-color: #e3f2fd;
margin-left: 2rem;
}
.message-input {
padding: 1rem;
border-top: 1px solid #ddd;
display: flex;
gap: 0.5rem;
}
.message-input input {
flex: 1;
padding: 0.5rem;
}
</style>
```
## 4. Gebruik in Je Applicatie
```javascript
// App.vue
<script setup>
import ChatInterface from '@/components/ChatInterface.vue'
</script>
<template>
<div id="app">
<ChatInterface />
</div>
</template>
```
## Belangrijke Performance Optimalisaties:
1. **Readonly State**: Gebruik `readonly()` om per ongeluk mutaties te voorkomen
2. **Efficiente Updates**: Batched updates via WebSocket messages
3. **Memory Management**: Beperk berichtengeschiedenis tot 100 items
4. **Computed Caching**: `sortedMessages` en `onlineUsersList` zijn gecached
5. **Connection Management**: Automatische reconnect met exponential backoff
6. **Event Handling**: Efficient message handling via Set collection
Deze architectuur zorgt voor naadloze realtime synchronisatie tussen componenten met optimale performance!
error: Generation failed [deepseek] prompt_id=4095 locale=en err=DeepSeek connection/timeout | Generation failed [deepseek] prompt_id=4095 locale=pt err=DeepSeek connection/timeout