Vue
Live before-and-after
Section titled “Live before-and-after”Executed source
Section titled “Executed source”Imported verbatim with ?raw from every implementation file shown below. Playback timing and FLIP controls come from the shared demo harness.
import { createApp, nextTick, shallowRef } from "vue";
import { mountFrameworkDemo, type DemoFrameState, type DemoRuntime } from "../shared/demo.js";
import Runtime from "./Runtime.vue";
await mountFrameworkDemo("Vue", (target, initialState): DemoRuntime => {
const frame = shallowRef<DemoFrameState>(initialState);
const app = createApp(Runtime, { frame });
app.mount(target);
return {
destroy: () => app.unmount(),
update: async (nextState) => {
frame.value = nextState;
await nextTick();
},
};
});
<script setup lang="ts">
import { useLikftc } from "@vp-tw/likftc/vue";
import { computed, type ShallowRef } from "vue";
import { createAfterRows, createBeforeRows, type DemoFrameState } from "../shared/demo.js";
import Row from "./Row.vue";
const props = defineProps<{ readonly frame: ShallowRef<DemoFrameState> }>();
const entries = useLikftc(() => props.frame.value.items, { getId: (item) => item.id });
const beforeRows = computed(() => createBeforeRows(props.frame.value));
const afterRows = computed(() => createAfterRows(props.frame.value, entries.value));
</script>
<template>
<div class="runtime-grid">
<article class="runtime-panel">
<small>WITHOUT</small>
<h3>Logical ID key</h3>
<ol data-list="before">
<Row v-for="row in beforeRows" :key="row.key" :row />
</ol>
</article>
<article class="runtime-panel">
<small>WITH @LIKFTC/VUE</small>
<h3>Presence identity</h3>
<ol data-list="after">
<Row v-for="row in afterRows" :key="row.key" :row />
</ol>
</article>
</div>
</template>
<script setup lang="ts">
import { describeRow, type DemoRenderedRow } from "../shared/demo.js";
defineProps<{ readonly row: DemoRenderedRow }>();
</script>
<template>
<li
class="runtime-row"
:data-collision="String(row.kind === 'collision')"
:data-id="row.item.id"
:data-key="row.keyText"
:data-kind="row.kind"
:data-phase="row.kind === 'exiting' ? 'exiting' : 'current'"
:data-slot="String(row.slot)"
>
<b>{{ row.item.id.toUpperCase() }}</b>
<span>{{ row.item.label }}</span>
<code>{{ row.keyText }}</code>
<em>{{ describeRow(row.kind) }}</em>
</li>
</template>
The executed example is a real Vue SFC with <script setup lang="ts">, a <template>, keyed v-for, and prop shorthand. The adapter uses Vue’s computed previous-value API, so no watcher can lag one render behind.
Vapor Mode is not enabled because it remains on Vue’s 3.6 prerelease line. The example stays on stable Vue 3.5 while using the current recommended Composition API shape.