Guide
Reactive Data
Bind reactive Vue refs and computed properties to Vue Plot marks so charts update automatically when data changes, filters, or swaps datasets.
Vue Plot automatically re-renders when your data changes. Bind reactive data to your marks — the plot re-renders on change.
Basic reactivity
App.vue
<script setup lang="ts">
import { ref } from 'vue'
import { VPlot } from '@memotux/vue-plot'
const data = ref([
{ x: 1, y: 2 },
{ x: 2, y: 4 },
{ x: 3, y: 1 },
])
</script>
<template>
<VPlot :width="680">
<PlotDot :data="data" x="x" y="y" />
</VPlot>
</template>
When data.value changes, the plot updates automatically.
Adding data points
App.vue
<script setup lang="ts">
import { ref } from 'vue'
import { VPlot } from '@memotux/vue-plot'
const data = ref([
{ x: 1, y: 2 },
{ x: 2, y: 4 },
{ x: 3, y: 1 },
])
function addPoint() {
data.value = [
...data.value,
{ x: data.value.length + 1, y: Math.random() * 10 },
]
}
</script>
<template>
<VPlot :width="680">
<PlotDot :data="data" x="x" y="y" r="4" />
</VPlot>
<button @click="addPoint">Add Point</button>
</template>
Always replace the array (immutable update) rather than mutating it with
push(). Vue's reactivity system tracks array references, not mutations.Filtering data
Use computed properties to derive filtered views:
App.vue
<script setup lang="ts">
import { ref, computed } from 'vue'
import { VPlot } from '@memotux/vue-plot'
const data = ref([
{ name: 'A', value: 10, category: 'odd' },
{ name: 'B', value: 20, category: 'even' },
{ name: 'C', value: 15, category: 'odd' },
{ name: 'D', value: 25, category: 'even' },
])
const filter = ref('all')
const filteredData = computed(() => {
if (filter.value === 'all') return data.value
return data.value.filter(d => d.category === filter.value)
})
</script>
<template>
<VPlot :width="680">
<PlotBarY :data="filteredData" x="name" y="value" />
</VPlot>
<button @click="filter = 'all'">All</button>
<button @click="filter = 'odd'">Odd</button>
<button @click="filter = 'even'">Even</button>
</template>
Updating marks reactively
When using the marks prop, wrap marks in a computed:
App.vue
<script setup lang="ts">
import { ref, computed } from 'vue'
import { VPlot } from '@memotux/vue-plot'
import { barY, ruleY } from '@observablehq/plot'
const data = ref([
{ name: 'A', value: 10 },
{ name: 'B', value: 20 },
])
const showAverage = ref(true)
const marks = computed(() => {
const m = [barY(data.value, { x: 'name', y: 'value' })]
if (showAverage.value) {
const avg = data.value.reduce((s, d) => s + d.value, 0) / data.value.length
m.push(ruleY([avg], { stroke: 'red', strokeDasharray: '4' }))
}
return m
})
</script>
<template>
<VPlot :width="680" :marks="marks" />
<label>
<input type="checkbox" v-model="showAverage" />
Show average
</label>
</template>
Swapping datasets
Replace the entire dataset to switch views:
App.vue
<script setup lang="ts">
import { ref, computed } from 'vue'
import { VPlot } from '@memotux/vue-plot'
const datasets = {
sales: [
{ month: 'Jan', revenue: 4000 },
{ month: 'Feb', revenue: 3000 },
{ month: 'Mar', revenue: 5000 },
],
users: [
{ month: 'Jan', revenue: 1200 },
{ month: 'Feb', revenue: 1500 },
{ month: 'Mar', revenue: 1800 },
],
}
const activeDataset = ref('sales')
const data = computed(() => datasets[activeDataset.value])
</script>
<template>
<VPlot :width="680">
<PlotBarY :data="data" x="month" y="revenue" />
</VPlot>
<button @click="activeDataset = 'sales'">Sales</button>
<button @click="activeDataset = 'users'">Users</button>
</template>
Performance considerations
For large datasets (10k+ points):
- Use
PlotDotwith small radius instead ofPlotBarY - Consider downsampling data before rendering
- Use
PlotHexbinorPlotDensityfor aggregated views
App.vue
<!-- Efficient rendering for large datasets -->
<VPlot :width="680" :height="400">
<PlotHexbin
:data="largeDataset"
x="longitude"
y="latitude"
fill="count"
/>
</VPlot>
What's next?
- Nuxt Integration — Nuxt module setup
- API Reference — Full component API
Marks as Props
Pass Observable Plot mark functions as props to build charts programmatically, with dynamic mark selection and no Vite plugin required.
Nuxt Integration
Install and configure the @memotux/nuxt-vue-plot module for auto-imports, custom-element compilation, and SSR-compatible chart rendering in Nuxt.