javascript - Vue.js 在替换列表上的转换

标签 javascript vue.js vuejs2 transition

我遇到了 vue.js 官方文档 here 中描述的问题,但有不同的数据。我想创建带有项目和子项目的树状结构来描述树(文件和文件夹结构就是一个很好的例子)。为了增强视觉效果,我想让它们滑动,但得到了。 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'
});
#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%);
}
<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>

最佳答案

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

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

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

delete props.mode

Evan You said :

This is unlikely to happen due to the sheer complexity - it will likely introduce too much extra code for a relatively non-critical use case, and the behavior of the transition modes on multiple items can be vague and hard to define. Even if we were to implement it, we'd probably ship it as a separate plugin instead of as part of core.

我打开了an issue在有关列表转换的文档中提及这一点。它现在位于 documentation 中。 :

Transition modes are not available, because we are no longer alternating between mutually exclusive elements.


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

提到了一个小解决方法 by NonPolynomial in the issue就是使用transition-delay将进入动画延迟到离开动画完成之后。

new Vue({
  el: '#app',
  data: {
    elements: [
      [1, 2, 3],
      [4, 5, 6, 7]
    ],
    index: 0
  },
});
.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;
}
<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/<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bbcdcedefb89958e958a8d" rel="noreferrer noopener nofollow">[email protected]</a>/dist/vue.js"></script>

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

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)
    }
  }
})
<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/<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="92e4e7f7d2a0bca7bca3a4" rel="noreferrer noopener nofollow">[email protected]</a>/dist/vue.js"></script>

关于javascript - Vue.js 在替换列表上的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46221656/

相关文章:

javascript - 在输入文本框中输入时显示图标

Javascript/Node.js : Convert array with sub-arrays into object

php - session 不在 Vue.js 和 Laravel 中存储数据

javascript - Vuejs 提交突变失败

vuejs2 - 自定义 Chart.js 的工具提示

javascript - 在 ember-cli 中安装 jQuery 插件

javascript - Vue.js - 无法将日期/时间选择器添加到 vue.js 渲染的 html 元素中

javascript - 从 Vue.js 2 中的方法内推送到数组

javascript - Vue.js API 获取

javascript - 如何在单击提交按钮之前隐藏标签?