iOSネイティブの日付/時刻ピッカーのようなカルーセルのようなリストを作成しようとしていますが、これは上下に移動できます。動的CSSプロパティを使用したVueリストのレンダリング
各項目の位置は、モデルからの属性であるtop
に基づいており、最終的に絶対配置で各リスト項目要素に割り当てられます。
私はそれが一方向に機能するように管理していたので、「上に行く」を押すと、それは私が望んでいたとおりに機能します(下のスニペットで調べることができます)。一方、同じコードを別の方向に使用する場合(.pop()
機能を.shift()
と.unshift()
〜.push()
に切り替える場合を除く)、別の方法で動作します。特に、項目値は再割り当てされますが、何も動きません。
私が気づいたのは、2番目のケースでは、アイテムキーが何らかの理由でリストアイテムがゼロからレンダリングされるということです。したがって、座標遷移は起こらない。
このメカニズムを両方向で動作させるにはどうすればよいですか?私は持っているように見える参照としてこのgithubの問題(github.com/vuejs/vue/issues/4834)を使用して
Vue.component('list-component', {
template: '#list-component',
name: 'list-componet',
data() {
\t return {
\t 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
});
}
\t }
},
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/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/moment.min.js"></script>
<script type="text/x-template" id="list-component">
\t <div class="wrapper">
\t <div class="container">
\t <div v-for="(item, iIndex) in model"
\t \t \t \t :key="item.value"
\t class="md-wheel-item"
\t :class="{'is-active': iIndex === activeIndex}"
\t :style="{height: itemHeight + 'px', top: item.top + 'px'}">
\t {{ item.value || item }}
\t </div>
</div>
<div class="buttons">
\t <button @click.prevent="shiftWheel('up')">Go up</button>
\t \t <button @click.prevent="shiftWheel('down')">Go down</button>
</div>
\t </div>
</script>
<div id="app">
<div id="content">
<list-component></list-component>
</div>
</div>
これは確かに難しいものです。この特定のユースケースについては、あなたがやりたいことに適しているため、vueの「移行グループ」を調べることをおすすめします:https://vuejs.org/v2/guide/transitions.html#List-Transitions –
@ b-fleming、それは確かにそれを解決する方法ですが、私はまだ私が上記のようにすることに興味があります。 btwは、あなたが提案したように、私が "transition-group"を使って作ったものです:https://jsfiddle.net/o_voloshin/mf5svm82/1/ –
@ b-flemingあなたは完全に正しいです。 githubの問題(https://github.com/vuejs/vue/issues/4834)を読むと、 'transition-group'が私の唯一の方法だと思われます。 –