【问题标题】:How to animate the sorting of a list with Vue.js如何使用 Vue.js 对列表的排序进行动画处理
【发布时间】:2015-12-01 04:05:09
【问题描述】:

我正在尝试使用 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>

【问题讨论】:

    标签: javascript css vue.js


    【解决方案1】:

    我认为问题是在排序过程中只有一个元素保留在 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>

    【讨论】:

    • 是的,你是对的。你有代码的想法吗?
    • 我添加了一个示例,说明如何在没有 Javascript 转换的情况下做到这一点。
    【解决方案2】:

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

    查看“List Move Transitions”和带有随机播放按钮的示例。

    【讨论】:

      猜你喜欢
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      • 2016-07-22
      • 1970-01-01
      • 2019-11-27
      • 2015-01-27
      • 2017-09-30
      • 2021-07-24
      相关资源
      最近更新 更多