首页 文章

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

提问于
浏览
2

我遇到了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'
});
#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>

1 回答

  • 1

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

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

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

    Evan You said

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

    我在列表转换的文档中提到了一个问题 . 它现在在documentation

    转换模式不可用,因为我们不再在互斥元素之间交替 .


    如何使用完整列表模拟输入转换

    提到的一个小解决方法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/vue@2.5.16/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/vue@2.5.16/dist/vue.js"></script>
    

相关问题