Могу ли я вставить вычисленное свойство в компонент Vue динамически - PullRequest
0 голосов
/ 01 октября 2018

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

Ниже приведен условный примеро том, что я пытаюсь сделать.Как я могу внести showItemX изменения в зависимости от текущего элемента?

<template>
  <ul>
    <li v-for="item in myArr" v-if="showItemX">
      {{ item.name }}
    </li>
  </ul>
</template>
<script>
  export default {
    data() {
      return {
        myArr: [{
          id: 'item1',
          name: 'Item 1'
        }, {
          id: 'item2',
          name: 'Item 2'
        }]
      };
    },
    computed: {
      showItem1: function() {
        return this.$store.state.showItem1;
      },
      showItem2: function() {
        return this.$store.state.showItem2;
      }
    }
  }
</script>

2 возможных решения

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

1.Вернуть единственный объект для вычисляемого свойства

. В этом варианте два вычисленных свойства выше будут объединены в одно свойство:

computed: {
  showItem: function() {
    return {
      item1: this.$store.state.showItem1,
      item2: this.$store.state.showItem2
    }
  }
}

Тогда для v-if будет задано значениеshowItem[item.id]:

<li v-for="item in myArr" v-if="showItem[item.id]">
  {{ item.name }}
</li>

Недостатком здесь является то, что кажется, что весь объект пересчитывается каждый раз, когда изменяется одна из зависимостей.

2.Используйте метод для получения соответствующего вычисляемого свойства

Здесь я попытался передать item.id методу в качестве способа доступа к соответствующему вычисляемому свойству:

computed: {
  item1Show: function() {
    return this.$store.state.showItem1;
  },
  item2Show: function() {
    return this.$store.state.showItem2;
  }
},
methods: {
  showItem: function(id) {
    return this[id + 'Show']
  }
}

И в шаблоне:

<li v-for="item in myArr" v-if="showItem(item.id)">
  {{ item.name }}
</li>

Опять же, в этом примере я не уверен, полностью ли я использую вычисленные свойства.


Если один из этих параметров предпочтительнее другого или являетсяЕсть ли лучший способ сделать это, что мне не хватает?

Ответы [ 2 ]

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

Есть лучший способ.

Для возможного решения № 1, вы также можете сделать

<li v-for="(item, index) in myArr" v-if="$store.state['showItem' + (index + 1)]">

Возможное решение № 2, вы полностью упустили оптимизацию Vue.Этот метод, хотя и не требует большого объема вычислений, будет перезапущен для каждого элемента каждого рендера.

Ниже приведено решение, которое соответствует конкретным параметрам вашей примерной задачи.Тем не менее, это не то, что я рекомендую здесь.Подробнее ниже.

<template>
      <ul>
        <!--
          `:key` is crucial for performance.
          otherwise, every element will re-render 
          whenever the filtered array updates.
        -->
        <li v-for="item in myFilteredArr" :key="item.id">
          {{ item.name }}
        </li>
      </ul>
</template>

<script>
  export default {
    data: _ => ({
      myArr: [
        {
          id: 'item1',
          name: 'Item 1'
        }, 
        {
          id: 'item2',
          name: 'Item 2'
        }
      ],
    }),

    computed: {
      myFilteredArr () {
        /* 
          abstracting state to a constant avoids 
          re-running the getter functions each iteration
        */
        const state = this.$store.state;
        return this.myArr.filter(
          (item, index) => state['showItem' + (index + 1)]
        );
      }
    }

  }
</script>

Моя реальная рекомендация - переместить всю эту логику в геттер Vuex.Вы можете прочитать о них здесь: https://vuex.vuejs.org/guide/getters.html.

Поскольку ваша логика фильтрации уже обрабатывается в хранилище, функцию, которая устанавливает все showItem, можно просто вырезать и вставить в геттер Vuex, возвращая myFilteredArr так же, каквыше.

Таким образом, нет взаимозависимости магазина <-> компонента, и состояние вашего магазина будет намного чище.

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

Приятная особенность Vue и JavaScript заключается в том, что вы можете использовать любой подход, соответствующий вашим потребностям, но, fwiw, я, вероятно, найду что-то вроде следующего, наиболее простое для понимания

<li v-for="item in myArr" v-if="showItem(item)">
    {{ item.name }}
</li>

И затем определитеshowItem метод, например

showItem(item) {
    return item.id === "item1" ?
        this.$store.state.showItem1 :
        this.$store.state.showItem2;
}

Предполагается, что вы не используете вычисленные свойства в других местах, не показанных в сообщении

...