The NOVA LAB module transport system allows you to connect different panels to the same station slot - an oxygen panel, water panel, or energy panel. Vue has a dynamic components mechanism - a special
<component> element with the :is attribute.1<script setup>
2import { ref, shallowRef } from 'vue'
3import OxygenPanel from './OxygenPanel.vue'
4import WaterPanel from './WaterPanel.vue'
5import SolarPanel from './SolarPanel.vue'
6
7const tabs = { OxygenPanel, WaterPanel, SolarPanel }
8const currentTab = shallowRef(OxygenPanel)
9</script>
10
11<template>
12 <div class="station">
13 <nav>
14 <button
15 v-for="(comp, name) in tabs"
16 :key="name"
17 @click="currentTab = comp"
18 >
19 {{ name }}
20 </button>
21 </nav>
22
23 <component :is="currentTab" />
24 </div>
25</template>We use
shallowRef instead of ref for components because we don't need deep reactivity on the component object.By default, switching a component destroys the old one and creates a new one. If you want to preserve state (e.g., form data), use
<KeepAlive>:1<template>
2 <KeepAlive>
3 <component :is="currentTab" />
4 </KeepAlive>
5</template>Now the component is cached - when you return to it, its state is preserved.
Control which components to cache:
1<template>
2 <!-- Only these components -->
3 <KeepAlive :include="['OxygenPanel', 'WaterPanel']">
4 <component :is="currentTab" />
5 </KeepAlive>
6
7 <!-- All except these -->
8 <KeepAlive :exclude="['HeavyModule']">
9 <component :is="currentTab" />
10 </KeepAlive>
11
12 <!-- Cache limit (LRU) -->
13 <KeepAlive :max="5">
14 <component :is="currentTab" />
15 </KeepAlive>
16</template>Cached components have additional hooks:
1<script setup>
2import { onActivated, onDeactivated } from 'vue'
3
4onActivated(() => {
5 console.log('Panel activated (visible)')
6 // Refresh data, resume timers
7})
8
9onDeactivated(() => {
10 console.log('Panel deactivated (hidden)')
11 // Stop timers, save state
12})
13</script>You can pass props to dynamic components:
1<template>
2 <component
3 :is="currentTab"
4 :station="stationData"
5 @alert="handleAlert"
6 />
7</template>