v-show на v-for создает нежелательный возвратный переход - PullRequest
0 голосов
/ 10 января 2019

У меня проблема с производительностью v-for для большого массива. Проблема в том, что v-for заново генерирует все отфильтрованные строки каждый раз, когда вы меняете фильтр. Мы решили это, выполнив комбинацию v-show и v-if для элемента v-for. Это сработало отлично, сэкономив ~ 700 мс при перерисовке каждый раз, когда вы фильтруете массив.

Недостатком этого является то, что transition-group go ??? (бананы)

Вы можете увидеть это в действии в примере ниже, отфильтровав что-то, а затем очистив фильтр. Используя v-show, элементы делают странный переход из верхнего левого угла. Это не то, что я ожидаю.

new Vue({
  el: "#app",
  data() {
    return {
      filter: null,
      people: [],
      useVshow: true,
      settings: {
        opacityOnly: false
      }
    }
  },

  created() {
    /* Irerelevant for issue - Just some fancy example code: */
    let arr = [];
    for (let i = 0; i < 500; ++i) {
      arr.push({
        id: i,
        name: `person ${i}`,
        age: i,
        face: Math.floor(Math.random() * 9),
        show: true
      });
    }
    this.people = arr;
  },

  computed: {
    filteredPeople: function() {
      return this.filter ? this.people.filter(person => person.name.includes(this.filter)) : this.people
    }
  },

  watch: {
    filter() {
      for (const i of this.people) {
        i.show = this.filter ? i.name.includes(this.filter) : true;
      }
    }
  }
})
.wrapper {
  position: relative;
}

.card {
  transition: all 800ms ease-in-out;
}

.opacity-only {
  transition: opacity 800ms ease-in-out;
}

.list-leave-active {
  position: absolute;
}

.list-enter,
.list-leave-to {
  opacity: 0;
  transform: translateY(30px);
}

.container {
  max-width: 520px;
  margin: 0 auto;
}


/* Irerelevant for issue - Just some fancy example code: */

input {
  width: 150px;
}

.card {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  margin: 10px 0;
}

.card .info p {
  margin: 5px 10px;
}

.card .info .name {
  font-weight: 600;
  color: #48484c;
}

.card .info .age {
  font-size: 14px;
  color: #656565;
}

.card .avatar {
  height: 80px;
  border-radius: 50%;
  border: 5px solid #ddd;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<main id="app">
  <div class="container">
    <label for="filter">Filter by name:</label>
    <input name="filter" v-model="filter"> Use v-show: <input type="checkbox" v-model="useVshow">
    <br>Only trantition opacity: <input type="checkbox" v-model="settings.opacityOnly">

    <transition-group name="list" tag="div" class="wrapper">

      <template v-if="useVshow">
        <div v-for="person in people" v-show="person.show" :key="person.id" class="card" :class="{'opacity-only': settings.opacityOnly}">
          <img class="avatar" :src="`https://randomuser.me/api/portraits/lego/${person.face}.jpg`">
          <div class="info">
            <p class="name">{{person.name}}</p>
            <p class="age">{{person.age}} years old</p>
          </div>
        </div>
      </template>

      <template v-else>
        <div v-for="person in filteredPeople" :key="person.id" class="card">
          <img class="avatar" :src="`https://randomuser.me/api/portraits/lego/${person.face}.jpg`">
          <div class="info">
            <p class="name">{{person.name}}</p>
            <p class="age">{{person.age}} years old</p>
          </div>
        </div>
      </template>

    </transition-group>
  </div>
</main>

Почему это происходит, и есть ли способ сделать возврат-переход таким же, как если бы у вас не было v-show?

EDIT: Добавлена ​​опция только для непрозрачности перехода, как указано @Sitethief

1 Ответ

0 голосов
/ 10 января 2019

Мне кажется, проблема в том, что transition: all применяет переход ко всем свойствам CSS. Это включает position: absolute;. Если вы проверяете разработчика при переключении фильтра, вы можете увидеть это вживую. Если вы измените переход на что-то вроде transition: opacity 800ms ease-in-out;, элементы списка не начнутся в левом углу.

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