How to set a component non-reactive data in Vue 2?
Solution 1
Vue sets all the properties in the data
option to setters/getters to make them reactive. See Reactivity in depth
Since you want myArray
to be static you can create it as a custom option which can be accessed using vm.$options
export default{
data() {
return{
someReactiveData: [1, 2, 3]
}
},
//custom option name myArray
myArray: null,
created() {
//access the custom option using $options
this.$options.myArray = ["value 1", "value 2"];
}
}
you can iterate over this custom options in your template as follows:
<template>
<ul>
<li v-for="item in $options.myArray">{{ item }}</li>
</ul>
</template>
Here is the fiddle
Solution 2
Actually, setting properties on this
in created()
should work out of the box:
<template>
<div id="app">
<ul>
<li v-for="item in myArray" :key="item">
{{ item }}
</li>
</ul>
</div>
</template>
<script>
export default {
name: "app",
created() {
this.myArray = [
'item 1',
'item 2'
];
}
};
</script>
will render
<div id="app">
<ul>
<li>
item 1
</li>
<li>
item 2
</li>
</ul>
</div>
Demo here: https://codesandbox.io/s/r0yqj2orpn .
Solution 3
I prefer using static data (non reactive) like this:
Create a mixin (i name it static_data.js
) with the follow content
import Vue from 'vue'
Vue.prototype.$static = {}
export default {
beforeCreate () {
const vue_static = this.$options.static
const vue_static_destination = this.$static || this
if (vue_static && typeof(vue_static) === 'function') {
Object.assign(vue_static_destination, vue_static.apply(this))
} else if (vue_static && typeof(vue_static) === 'object') {
Object.assign(vue_static_destination, vue_static)
}
}
}
In your components where you want to use static data you can do:
import use_static_data from '@mixins/static_data'
export default {
mixins: [use_static_data],
static: () => ({
static_value: 'Vue is awesome'
}),
created () {
console.log(this.$static.static_value); // Vue is awesome
}
}
There is also a package vue-static
Credits here.
Solution 4
If you want to keep it in data
, the proper way is using Object.freeze(), as described in the documentation:
The only exception to this being the use of Object.freeze(), which prevents existing properties from being changed, which also means the reactivity system can’t track changes.
Admin
Updated on July 09, 2022Comments
-
Admin almost 2 years
I have a categories array, which is loaded once (in created hook) and then it is static all the time. I render this array values in a component template.
<template> <ul> <li v-for="item in myArray">{{ item }}</li> </ul> </template>
My data property looks (it does not include myArray - I dont want reactive binding):
data() { return { someReactiveData: [1, 2, 3] }; }
My create hook:
created() { // ... this.myArray = ["value 1", "value 2"]; // ... }
Problem is, that Vue throw error - I cant use myArray in a template, because this variable is not created when the DOM is created - mounted.
So how to do this? Or where can be stored component constants?