如何使用Vue.js为列表排序设置动画

时间:2015-09-04 22:36:24

标签: javascript css vue.js

我正在尝试使用Vue.js对列表进行排序动画,但并非所有项目都是动画的。你知道为什么吗?以及如何使其发挥作用?

new Vue({
  el: '#app',
  data: {
    reverse: 1,
    items: [
      { name: 'Foo' },
      { name: 'Bar' },
      { name: 'Baz' },
      { name: 'Qux' }
    ]
  }
})
.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;
}
<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>

2 个答案:

答案 0 :(得分:5)

我认为问题是在排序过程中只有一个元素留在DOM中。其他三个被删除并重新插入以满足新的排序 - 但结果他们没有触发动画。

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

如果您确实需要从旧位置动画到新位置,我认为您需要编写自己的Javascript转换,以便在删除每个项目之前记住每个项目的先前位置,并将其动画设置为新位置它被插入。

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

另一种选择是不按过滤器排序,而是在javascript中进行排序(这样v-for只渲染一次)。然后针对项目上的新索引参数定位绑定样式,如下所示:

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

答案 1 :(得分:1)

V2具有以下内置功能:https://vuejs.org/v2/guide/transitions.html#Transition-Modes

使用“随机播放”按钮查看“列表移动过渡”和示例。

相关问题