我遇到了 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
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/