简体   繁体   中英

How to set a component non-reactive data in Vue 2?

I have a categories array, which is loaded once (in created hook) and then it is static all the time. I render these 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 don't want reactive binding):

data() {
    return {
        someReactiveData: [1, 2, 3]
    };
}

My create hook:

created() {
    // ...
    this.myArray = ["value 1", "value 2"];
    // ...
}

Problem is, that Vue throws error - I can't 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?

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

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 .

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 .

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.

You can try this line of code. You can copy an object and remove the reactivity.

var newObj = JSON.parse(JSON.stringify(obj));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM