Vue guide
The Vue adapter lets Vue 3 drive the same native Fabric engine as React, Angular, Svelte, and Solid. The native output is not DOM and not a WebView: Vue renderer operations become engine mutations, then Fabric commits real native views.
SFC or JSX — your choice
Section titled “SFC or JSX — your choice”Vue components can be authored as a .vue single-file component or as Vue
JSX/TSX (@vue/babel-plugin-jsx compiling to createVNode calls) — both
compile down to the exact same @vue/runtime-core vnode tree, so both drive
the identical adapter, the identical component surface, and the identical
native output. Neither is a reduced mode of the other.
Vue SFC (.vue) — the reference canary at examples/vue-sfc.
Vue JSX/TSX (.tsx) — the same canary, authored render-function-first at
examples/vue-tsx, proving the component surface is template-agnostic.
Minimal component
Section titled “Minimal component”<script setup lang="ts">import { ref } from 'vue';
const count = ref(0);</script>
<template> <view class="root"> <pressable @press="count++" v-slot="{ pressed }"> <text :class="pressed ? 'pressed' : 'label'"> Count is {{ count }} </text> </pressable> </view></template>
<style scoped>.root { flex: 1; align-items: center; justify-content: center;}.label { font-size: 24px;}.pressed { font-size: 24px; opacity: 0.6;}</style>view, pressable, and text are intrinsic tags — no import needed. Only a
composed component (FlatList, SectionList, VirtualizedList,
VirtualizedSectionList, KeyboardAvoidingView, …) still comes from
@symbiote-native/vue.
StyleSheet.create works identically if you’d rather keep style objects
inline instead of an SFC <style> block — see the
Styling guide for both paths.
Vue contract
Section titled “Vue contract”Vue uses Vue-shaped APIs where the framework semantics differ from React:
- framework events are typed emits such as
@pressand@value-change(shared bySwitchandTextInput); - dynamic children use slots and scoped slots instead of React render props;
- template attributes can use kebab-case, and the adapter folds them to the native camelCase contract before commit;
- imperative handles are exposed through Vue template refs;
- controlled-value components (
Switch,TextInput, the Slider wrapper) support real Vuev-model, alongside the explicitvalue/@change-*pair; v-showworks on any SymbioteNative host node — it toggles nativedisplay: noneinstead of unmounting, same semantics as Vue’s DOMv-show.
<switch v-model="enabled" /><text-input v-model="text" /><view v-show="visible"> <text>Hidden without unmounting</text></view>v-model is sugar over the same contract that was already there: Switch
and TextInput both still accept the explicit :value/@value-change pair
— TextInput’s @value-change fires with (text, event), so the raw native
event is still reachable without a separate handler. Bare v-model="x"
compiles to :model-value="x" + @update:model-value; every model-capable
component also accepts the named form v-model:value="x". Mixing v-model
with the explicit value/@value-change pair on the same element is
redundant but harmless — both fire.
Read the exact API surface in the Vue API reference.