我试图制作类似旋转木马的项目列表(例如那些iOS原生日期/时间选择器),这些项目可以向上或向下移动。
每个项目的位置基于模型的top
属性,最终以绝对定位分配给每个列表项元素。
我设法让它在一个方向上工作,所以如果你按“上升”,它就会按照我想要的功能运行(你可以在下面的代码片段中查看)。另一方面,当我将相同的代码用于另一个方向时(除了我将.pop()
函数切换为.shift()
和.unshift()
改为.push()
),它的工作方式不同,特别是项目值被重新分配,但没有任何动作。
我注意到,在第二种情况下,列表项目由于某种原因从头开始呈现,尽管有项目键。因此,坐标转换不会发生。
如何使此机制在两个方向都有效?请随意查看我准备的片段:
Vue.component('list-component', {
template: '#list-component',
name: 'list-componet',
data() {
return {
model: [],
activeIndex: null,
itemHeight: 56,
}
},
methods: {
shiftWheel(direction) {
if (direction === 'up') {
const value = this.model[0].value - 1;
this.model.map((v) => {
v.top += this.itemHeight;
});
this.model.pop();
this.model.unshift({
value,
top: -this.itemHeight
});
} else {
const value = this.model[this.model.length - 1].value + 1;
this.model.shift();
this.model.forEach((v) => {
v.top -= this.itemHeight;
});
this.model.push({
value,
top: this.itemHeight * 5
});
}
}
},
mounted() {
const quantity = 5 + 2;
this.top = -56;
const currentYear = moment().year;
const toTheSides = Math.floor(quantity / 2);
this.activeIndex = quantity - toTheSides - 1;
const start = moment().clone().subtract(toTheSides, 'Y');
this.model = Array(quantity).fill().map((v, i) => {
const value = start.clone();
start.add(1, 'Y');
return {
value: value.year(),
top: i * this.itemHeight - this.itemHeight
};
});
}
});
new Vue({
el: '#app'
});

.container {
position: relative;
overflow: hidden;
height: 280px;
width: 50px;
}
.wrapper {
display: flex;
align-items: center;
}
.buttons {
position: relative;
z-index: 999;
}
.md-wheel-item {
padding: 16px 0;
display: flex;
position: absolute;
flex: 1;
align-items: center;
justify-content: center;
transition: top .2s ease-in-out;
will-change: top;
&.is-active {
color: red;
}
}

<script src="https://unpkg.com/vue@2.4.2/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment@2.19.1/moment.min.js"></script>
<script type="text/x-template" id="list-component">
<div class="wrapper">
<div class="container">
<div v-for="(item, iIndex) in model"
:key="item.value"
class="md-wheel-item"
:class="{'is-active': iIndex === activeIndex}"
:style="{height: itemHeight + 'px', top: item.top + 'px'}">
{{ item.value || item }}
</div>
</div>
<div class="buttons">
<button @click.prevent="shiftWheel('up')">Go up</button>
<button @click.prevent="shiftWheel('down')">Go down</button>
</div>
</div>
</script>
<div id="app">
<div id="content">
<list-component></list-component>
</div>
</div>
&#13;
答案 0 :(得分:0)
使用此github问题(github.com/vuejs/vue/issues/4834)作为参考,看起来我只需要使用transition-group
:
它们不是重新创建的(项目),而是由insertBefore移动。如果在转换期间移动了具有转换的元素,则转换将被中断。当完成所有操作时,键确保元素在DOM中的正确位置结束,但不保证它们在过程中永远不会移动。这是确保具有一致结果的简洁算法所必需的。这可能会在未来得到改善,但这不是非常关键的事情