Как установить компонентные нереактивные данные в Vue 2?

У меня есть массив категорий, который загружается один раз (в созданном крючке), а затем он постоянно статичен. Я представляю эти значения массива в шаблоне компонента.

<template>
    <ul>
        <li v-for="item in myArray">{{ item }}</li>
    </ul>
</template>

Свойство моих данных выглядит (оно не включает myArray - я не хочу реактивной привязки):

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

Мой крючок создания:

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

Проблема в том, что ошибка Vue throw - я не могу использовать myArray в шаблоне, потому что эта переменная не создается, когда DOM создается - монтируется.

Итак, как это сделать? Или где могут храниться константы компонента?

Ответ 1

Vue устанавливает все свойства в опции data для сеттеров/геттеров, чтобы сделать их реактивными. См Реактивность в глубине

Поскольку вы хотите, чтобы myArray был статическим, вы можете создать его как пользовательский параметр, доступ к которому можно получить с помощью 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"];
    }
}

Вы можете перебирать эти пользовательские параметры в своем шаблоне следующим образом:

<template>
    <ul>
        <li v-for="item in $options.myArray">{{ item }}</li>
    </ul>
</template>

Вот скрипка

Ответ 2

На самом деле, установка свойств для this в created() должна работать из коробки:

<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>

будет оказывать

<div id="app">
  <ul>
    <li>
      item 1
    </li>
    <li>
      item 2
    </li>
  </ul>
</div>

Демо здесь: https://codesandbox.io/s/r0yqj2orpn.

Ответ 3

  Я предпочитаю использовать статические данные (не реактивные), как это:

Создайте миксин (я назову его static_data.js) со следующим содержанием

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)
    }      
  }
}

В ваших компонентах, где вы хотите использовать статические данные, вы можете сделать:

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
  }
}

Существует также пакет vue-static

Кредиты здесь.

Ответ 4

Если вы хотите сохранить его в data, правильным способом является использование Object.freeze(), как описано в документации:

Единственным исключением является использование Object.freeze(), который предотвращает изменение существующих свойств, что также означает, что система реактивности не может отслеживать изменения.