Vue.js在替换列表时进行转换

时间:2017-09-14 14:23:51

标签: javascript vue.js vuejs2 transition

我遇到了vue.js官方文档here中描述的问题,但与kidna有不同的数据。我想创建树状结构,用项目和子项来描述树(文件和文件夹结构就是很好的例子)。为了做一些视觉增强,我想让它们滑动,但得到了。 mode="out-in"已设置且无效。

知道如何解决这种转变吗?



Vue.component('booster', {
    props: {
        item: {
            type: Object
        }
    },
    template: '<div class="booster" @click="$emit(\'click\')"><img :src="item.image"></div>'
});

Vue.component('boosters', {
    data: function() {
        return {
            boosters: this.items,
            path: [],
            root: this.items
        };
    },
    props: {
        items: {
            type: Array
        },
        item_up: {
            type: Object,
            default: function() {
                return {
                    name: "Up",
                    image: "http://via.placeholder.com/128x178/000000/ffffff?text=↑"
                };
            }
        }
    },
    methods: {
        navigate: function(item) {
            var self = this;
            if (item === self.item_up && self.path.length) {
                self.root = self.path.pop();
            } else if ("undefined" !== typeof item.items) {
                self.path.push(self.root);
                self.root = [self.item_up].concat(item.items);
            } else {
                console.log(item.name);
            }
        }
    },
    template: '<transition-group name="slide" mode="out-in" tag="div" class="boosters"><template v-for="item in root"><booster :item="item" :key="item.name" @click="navigate(item)"></booster></template></transition-group>'
});

var vue = new Vue({
    el: '#content'
});
&#13;
#content {
    margin: 4rem;
}

.boosters {
    display: flex;
    flex-wrap: wrap;
    align-content: center;
}

.booster {
    box-shadow: 0px 0px 6px 3px black;
    box-sizing: border-box;
    margin: 15px;
}

.booster img {
    width: 128px;
    height: 178px;
    display: block;
}

.slide-enter-active, .slide-leave-active {
    transition: all 0.6s ease-in-out;*/
}

.slide-move {
    transition: transform 0.5s;
}

.slide-enter {
    transform: translateY(-100%);
}

.slide-leave-to {
    transform: translateY(100%);
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.3/vue.min.js"></script>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
<div id="content">
    <boosters :items='[
            {name:"First",image:"http://via.placeholder.com/128x178?text=1",items:[
                {name:"Sub-first-1",image:"http://via.placeholder.com/128x178?text=1.1"},
                {name:"Sub-first-2",image:"http://via.placeholder.com/128x178?text=1.2"}
                ]},
            {name:"Second",image:"http://via.placeholder.com/128x178?text=2", items:[
                {name:"Sub-second-1",image:"http://via.placeholder.com/128x178?text=2.1"},
                {name:"Sub-second-2",image:"http://via.placeholder.com/128x178?text=2.2"}
                ]},
            {name:"Third",image:"http://via.placeholder.com/128x178?text=3"}
            ]'>
    </booster>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>
    </div>
</body>
</html>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:2)

为什么带模式的转换组什么都不做?

transition-group没有mode道具。它已从transition-group.js component source中的道具中明确删除:

const props = extend({
  tag: String,
  moveClass: String
}, transitionProps)

delete props.mode

作为Evan You said

  

由于纯粹的复杂性,这种情况不太可能发生 - 它可能会为相对非关键的用例引入过多的额外代码,并且多个项目的转换模式的行为可能很模糊且难以定义。即使我们要实现它,我们也可能将其作为单独的插件而不是作为核心的一部分发布。

我在列表转换的文档中打开了an issue来提及。现在它在documentation

  

Transition modes不可用,因为我们不再在互斥元素之间交替。

如何使用完整列表模拟out-in转换

提到by NonPolynomial in the issue的一个小解决方法是使用transition-delay在完成离开动画后延迟输入动画。

&#13;
&#13;
new Vue({
  el: '#app',
  data: {
    elements: [
      [1, 2, 3],
      [4, 5, 6, 7]
    ],
    index: 0
  },
});
&#13;
.fade-out-in-enter-active,
.fade-out-in-leave-active {
  transition: opacity .5s;
}

.fade-out-in-enter-active {
  transition-delay: .5s;
}

.fade-out-in-enter,
.fade-out-in-leave-to {
  opacity: 0;
}
&#13;
<div id="app">
  <button type="button" @click="index = (index + 1) % elements.length">Swap</button>

  <transition-group tag="ul" name="fade-out-in">
    <li v-for="num in elements[index]" :key="num">
      {{num}}
    </li>
  </transition-group>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
&#13;
&#13;
&#13;

作为替代方案,Staggering List Transitions上的文档提供了一个很好的示例,说明如何使用JavaScript处理完全控制的转换。

&#13;
&#13;
new Vue({
  el: '#staggered-list-demo',
  data: {
    query: '',
    list: [
      { msg: 'Bruce Lee' },
      { msg: 'Jackie Chan' },
      { msg: 'Chuck Norris' },
      { msg: 'Jet Li' },
      { msg: 'Kung Fury' }
    ]
  },
  computed: {
    computedList: function () {
      var vm = this
      return this.list.filter(function (item) {
        return item.msg.toLowerCase().indexOf(vm.query.toLowerCase()) !== -1
      })
    }
  },
  methods: {
    beforeEnter: function (el) {
      el.style.opacity = 0
      el.style.height = 0
    },
    enter: function (el, done) {
      var delay = el.dataset.index * 150
      setTimeout(function () {
        Velocity(
          el,
          { opacity: 1, height: '1.6em' },
          { complete: done }
        )
      }, delay)
    },
    leave: function (el, done) {
      var delay = el.dataset.index * 150
      setTimeout(function () {
        Velocity(
          el,
          { opacity: 0, height: 0 },
          { complete: done }
        )
      }, delay)
    }
  }
})
&#13;
<div id="staggered-list-demo">
  <input v-model="query">
  <transition-group
    name="staggered-fade"
    tag="ul"
    v-bind:css="false"
    v-on:before-enter="beforeEnter"
    v-on:enter="enter"
    v-on:leave="leave"
  >
    <li
      v-for="(item, index) in computedList"
      v-bind:key="item.msg"
      v-bind:data-index="index"
    >{{ item.msg }}</li>
  </transition-group>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
&#13;
&#13;
&#13;