$options shared between instances if used in mixins
Vue version
3.2.47
Link to minimal reproduction
Steps to reproduce
Open the reproduction playground above, then open your DevTool and observe the console.
What is expected?
$options are shared! Value is: foo
should not be logged to the console
What is actually happening?
$options are shared! Value is: foo
is logged to the console
System Info
No response
Any additional comments?
In Vue 2 I used to attach instances of 3rd party plugins onto this
using the created()
hook. With Vue 3, that doesn't play well anymore with Typescript, so I followed this comment and used the $options
object instead.
However, when using that approach in a mixin for a component that is used several times, the property value attached to $options
becomes shared across instances.
I'm hesitant to rate this a bug, it's an implementation detail. Nathalia's recommendation here was likely made while being unaware of that detail.
What you can rather do, is have a real cache for this and some explicit methods to get and set it, i.e.:
@LinusBorg Thank you for this. Works like a charm!
For iternity, the suggested way to store something on the vue instance (non-reactive) is to use a WeakMap() as cache like that:
import type { ComponentPublicInstance } from 'vue'
import * as Highcharts from 'highcharts'
const cache = new WeakMap<ComponentPublicInstance, Highcharts.Chart>()
export default {
mounted() {
const chart = Highcharts.chart('chart-id', { /* chartOptions */ })
this.setChart(chart)
},
methods: {
setChart(chart: Highcharts.Chart) { cache.set(this, chart) },
getChart() { return cache.get(this) }
},
beforeUnmount() {
this.getChart().destroy()
}
}
Feel free to close this issue if you don't consider it as a bug after all.