Повышение производительности для многих компонентов Vue на одной странице - PullRequest
0 голосов
/ 03 октября 2018

Я создаю приложение, которое монтирует сотни или даже тысячи экземпляров компонента vue в одном представлении.Каждый компонент имеет идентификатор, который ссылается на объект в хранилище vuex.

<my-component :id="item1"></my-component>
<my-component :id="item2"></my-component>
<my-component :id="item3"></my-component>
...

Хранилище:

state: {
  myComponentData: [
    {
      id: 'item1',
      name: 'Hawaiian Shirt', 
      selected: false,
      // ...
    },
    // ...
  ]
}

В my-component я ищу его объект в магазине и сохраняю его в вычисленном свойстве:

computed: {
  myComponentData: function () {
    return this.$store.state.myComponentData.find(el => el.id === this.id);
  },
  isSelected: function () {
    return this.myComponentData.selected;
  },
  // ...
}

Свойствами объекта в хранилище можно манипулировать, взаимодействуя с самим компонентом или другими компонентами в другом месте приложения.

Проблема в том, что когда я пытаюсь запустить это с несколькими сотнями или более 1000 элементов, требуется 30или более секунд для загрузки.

Если я удаляю вычисленные свойства или заменяю их статическими значениями, то страница загружается без проблем.У меня возникают проблемы с запаздыванием только при попытке загрузить все вычисленные свойства из магазина.

Есть ли способ повысить производительность при загрузке многих (более 1500) компонентов Vue, которые используют вычисленные свойства и Vuex?Я рассмотрел динамические / асинхронные компоненты, vue-async-computed и vue-rx как возможные решения, но я не уверен, что поможет в этом случае.

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

Я думаю, что операция Array.find() самая дорогая.Наличие его в свойстве computed означает, что оно запускается при каждом изменении зависимостей.

Вы можете получить индекс массива в mounted() и использовать его в вычисленном,

export default {
  name: "MyComponent",
  props: ["id"],
  data() {
    return {
      storeIndex: -2
    };
  },
  mounted() {
    this.storeIndex = this.$store.state.myComponentData.findIndex(
      el => el.id == "item" + this.id
    );
  },
  computed: {
    myComponentData: function() {
      // return this.$store.state.myComponentData.find(
      //   el => el.id === "item" + this.id
      // );
      return this.$store.state.myComponentData[this.storeIndex] || {};
    },
    isSelected: function() {
      return this.myComponentData.selected;
    }
  }
};

Вот CodeSandbox с рабочим примером.

0 голосов
/ 03 октября 2018

Проблема в логике.Если у вас есть 1000 предметов, вы создаете 1000 компонентов.Затем каждый из них перебирает по списку предметов, чтобы найти подходящий по идентификатору.Таким образом, вы в основном делаете циклы 1000 * 1000 (конечно, в худшем случае).Что не самое плохое - вы добавляете реактивность через это вычисленное свойство!Каждый раз, когда что-то меняется, вычисляемый метод запускается снова, приводя к следующему циклу 1000 (худший вариант, если ваш элемент последний).

У вас есть несколько вариантов:

  1. Получить элемент магазина при настройке данных в вашем компоненте.Это не создаст вычисляемое свойство, поэтому у вас будут статические данные.Это приведет к созданию ваших собственных наблюдателей за всеми данными, которые вы хотите изменить.

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

Просто не добавляйте так многоциклы и вычисляемые свойства - как следует из названия, они предназначены для вычислений , а не для фильтрации чего-то, что вы можете фильтровать в другом месте;)

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...