如何使用Vue.js动画化列表排序

Sam*_*ker 3 javascript css vue.js

我正在尝试使用Vue.js动画化列表的排序,但并非所有项目都具有动画效果。你知道为什么吗?以及如何使其工作?

new Vue({
  el: '#app',
  data: {
    reverse: 1,
    items: [
      { name: 'Foo' },
      { name: 'Bar' },
      { name: 'Baz' },
      { name: 'Qux' }
    ]
  }
})
Run Code Online (Sandbox Code Playgroud)
.moving-item {
  transition: all 1s ease;
  -webkit-transition: all 1s ease;
}
ul {
  list-style-type: none;
  padding: 0;
  position: relative;
}
li {
  position: absolute;
  border: 1px solid #42b983;
  height: 20px;
  width: 150px;
  padding: 5px;
  margin-bottom: 5px;
  color: #42b983;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.0-alpha.2/vue.min.js"></script>
<div id="app">
  <button on-click="reverse = Math.abs(reverse-1)">
    <span v-if="reverse == 0">?</span>
    <span v-if="reverse == 1">?</span> Order
  </button>
  <ul>
    <li class="moving-item" v-for="item in items | orderBy 'name' reverse" bind-style="{ top: ($index * 35) + 'px'}">{{ item.name }}</li>
  </ul>  
</div>
Run Code Online (Sandbox Code Playgroud)

Dav*_*ess 5

我认为问题在于排序期间DOM中仅保留了一个元素。其他三个将被删除并重新插入以满足新的顺序,但结果是它们没有触发动画。

通常,动画是使用Vue过渡系统(http://vuejs.org/guide/transitions.html)完成的。但是,使用该技术会发生删除和重新插入而不跟踪位置状态的相同基本问题。通常,动画的制作不受其先前和新位置的影响(例如,旧位置的淡入和新位置的淡入)。

如果您确实需要从旧的位置动画到新的位置,我想您需要编写自己的Javascript过渡,该过渡要记住每个项目的先前位置,然后再将其动画化为插入时的新位置。

这里有一个示例,应该是一个很好的起点:http : //vuejs.org/guide/transitions.html#JavaScript_Only_Transitions

另一种选择是不按过滤器排序,而是使用javascript进行排序(以便v-for仅呈现一次)。然后将您的绑定样式针对项目上的新index参数,如下所示:

new Vue({
  el: '#app',
  data: {
    reverse: 1,
    items: [
      { name: 'Foo', position: 0 },
      { name: 'Bar', position: 1 },
      { name: 'Baz', position: 2 },
      { name: 'Qux', position: 3 }
    ]
  },
  methods: {
    changeOrder: function (event) {
      var self = this;
      self.reverse = self.reverse * -1
      var newItems = self.items.slice().sort(function (a, b) { 
        var result;
        if (a.name < b.name) {
          result = 1
        }
        else if (a.name > b.name) {
          result = -1
        }
        else {
          result = 0
        }
        return result * self.reverse
      })
      newItems.forEach(function (item, index) {
        item.position = index;
      });
    }
  }
})
 
Run Code Online (Sandbox Code Playgroud)
.moving-item {
  transition: all 1s ease;
  -webkit-transition: all 1s ease;
}
ul {
  list-style-type: none;
  padding: 0;
  position: relative;
}
li {
  position: absolute;
  border: 1px solid #42b983;
  height: 20px;
  width: 150px;
  padding: 5px;
  margin-bottom: 5px;
  color: #42b983;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.0-alpha.2/vue.min.js"></script>
<div id="app">
  <button on-click="changeOrder">
    <span v-if="reverse == -1">?</span>
    <span v-if="reverse == 1">?</span> Order
  </button>
  <ul>
    <li class="moving-item" v-for="item in items" bind-style="{ top: (item.position * 35) + 'px'}">{{ item.name }}</li>
  </ul>  
</div>
Run Code Online (Sandbox Code Playgroud)


Dav*_*vis 5

V2 内置了这个: https: //v2.vuejs.org/v2/guide/transitions.html#Transition-Modes

查看“列出移动转换”和带有随机播放按钮的示例。