Asked By: Anonymous
I’m trying to add transitions to my form, so that when a user selects a specific answer to a question, it will dynamically show the next question. Currently I have it looking something like this:
<input type="text" :value="vueModel.question1" />
<div v-if="vueModel.question1 === 'hello'">
//Do something
</div>
<div v-else-if="vueModel.question1 === 'hihi'">
//Do something
</div>
<div v-else>
//Do something
</div>
My question is, should I be adding transitions this way? (and why?)
<input type="text" :value="vueModel.question1" />
<transition-group name="slide-fade" mode="in-out">
<div v-if="vueModel.question1 === 'hello'" key="key1">
//Do something
</div>
<div v-else-if="vueModel.question1 === 'hihi'" key="key2">
//Do something
</div>
<div v-else key="key3">
//Do something
</div>
</transition-group>
or, this way? (and why?)
<input type="text" :value="vueModel.question1" />
<transition name="slide-fade" mode="in-out">
<div v-if="vueModel.question1 === 'hello'" key="key1">
//Do something
</div>
<div v-else-if="vueModel.question1 === 'hihi'" key="key2">
//Do something
</div>
<div v-else key="key3">
//Do something
</div>
</transition>
Or, is there another way I could do this better and which fits with Vue best practices?
Solution
Answered By: Anonymous
So when you we have a list of items and you want to render and filter simultaneously, for example with v-for
? In this case, you may use transition-group
component. Unlike transition
, this will render an actual element: like div
in the next sniped. However, you can change the element that is rendered with the tag
attribute.
NOTE
Elements inside are always required to have a unique key attribute.
Update
If you just have a question and then you want to “do something” use only transition
as in this sample.
The main difference between transition
and transition-group
is that transition will affect one component. This means if you have a component an you want to replaced with another component you can use transition.
new Vue({_x000D_
el: '#vue-transition',_x000D_
data: {_x000D_
show: false,_x000D_
}_x000D_
})
_x000D_
<a href="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js">https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js</a>_x000D_
<link href="https://cdn.jsdelivr.net/npm/[email protected]" rel="stylesheet" type="text/css">_x000D_
_x000D_
<div id="vue-transition">_x000D_
<button @click="show = !show"> Simple Transition </button>_x000D_
<transition_x000D_
name="custom-classes-transition"_x000D_
enter-active-class="animated tada"_x000D_
leave-active-class="animated bounceOutRight"_x000D_
>_x000D_
<p v-if="show">Teocci</p>_x000D_
</transition>_x000D_
</div>
_x000D_
_x000D_
x000D
On the other hand, transition-group
renders an actual element from a list of elements, for that reason elements inside are always required to have a unique key attribute. For example, if you have 9 questions but you want to render a transition of each element moving randomly to another position in the SAME group.
new Vue({_x000D_
el: '#list-complete-demo',_x000D_
data: {_x000D_
items: [1, 2, 3, 4, 5, 6, 7, 8, 9],_x000D_
},_x000D_
methods: {_x000D_
shuffle: function() {_x000D_
this.items = _.shuffle(this.items)_x000D_
}_x000D_
}_x000D_
})
_x000D_
.list-complete-item {_x000D_
transition: all 1s;_x000D_
display: inline-block;_x000D_
margin-right: 10px;_x000D_
}_x000D_
_x000D_
.list-complete-enter,_x000D_
.list-complete-leave-to {_x000D_
opacity: 0;_x000D_
transform: translateY(30px);_x000D_
}_x000D_
_x000D_
.list-complete-leave-active {_x000D_
position: absolute;_x000D_
}
_x000D_
<a href="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js">https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js</a>_x000D_
<a href="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js">https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js</a>_x000D_
_x000D_
<div id="list-complete-demo" class="demo">_x000D_
<button v-on:click="shuffle">Shuffle</button>_x000D_
<transition-group name="list-complete" tag="p">_x000D_
<span v-for="item in items" v-bind:key="item" class="list-complete-item">_x000D_
{{ item }}_x000D_
</span>_x000D_
</transition-group>_x000D_
</div>
_x000D_
_x000D_
x000D
For that reason, if you just want to “do something” use transition
as shown in this snippet to achieve what you want.
let app = new Vue({_x000D_
el: '#vue-selector',_x000D_
data: {_x000D_
questions: [{_x000D_
id: 0,_x000D_
description: 'Question 01',_x000D_
answer: 'hihi'_x000D_
},_x000D_
{_x000D_
id: 1,_x000D_
description: 'Question 02',_x000D_
answer: 'lala'_x000D_
},_x000D_
{_x000D_
id: 2,_x000D_
description: 'Question 03',_x000D_
answer: 'hello'_x000D_
},_x000D_
{_x000D_
id: 3,_x000D_
description: 'Question 04',_x000D_
answer: 'none'_x000D_
},_x000D_
{_x000D_
id: 4,_x000D_
description: 'Question 05',_x000D_
answer: 'teo'_x000D_
},_x000D_
],_x000D_
answer: {_x000D_
question: -1,_x000D_
text: '',_x000D_
},_x000D_
answerText: '',_x000D_
selected: '',_x000D_
},_x000D_
computed: {_x000D_
computedQuestions: function() {_x000D_
let vm = this;_x000D_
return this.questions.filter(function(item, index) {_x000D_
return index !== vm.answers;_x000D_
})_x000D_
}_x000D_
},_x000D_
methods: {_x000D_
answerQuestion: function(index) {_x000D_
this.answer.question = index;_x000D_
this.answer.text = this.answerText;_x000D_
},_x000D_
beforeEnter: function(el) {_x000D_
el.style.opacity = 0_x000D_
el.style.height = 0_x000D_
},_x000D_
enter: function(el, done) {_x000D_
var delay = el.dataset.index * 150_x000D_
setTimeout(function() {_x000D_
Velocity(_x000D_
el, {_x000D_
opacity: 1,_x000D_
height: '1.6em'_x000D_
}, {_x000D_
complete: done_x000D_
}_x000D_
)_x000D_
}, delay)_x000D_
},_x000D_
leave: function(el, done) {_x000D_
var delay = el.dataset.index * 150_x000D_
setTimeout(function() {_x000D_
Velocity(_x000D_
el, {_x000D_
opacity: 0,_x000D_
height: 0_x000D_
}, {_x000D_
complete: done_x000D_
}_x000D_
)_x000D_
}, delay)_x000D_
},_x000D_
},_x000D_
});
_x000D_
div.selector {_x000D_
display: block;_x000D_
padding-top: 25px;_x000D_
padding-bottom: 125px;_x000D_
}
_x000D_
<a href="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js">https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js</a>_x000D_
<a href="//cdnjs.cloudflare.com/ajax/libs/velocity/2.0.3/velocity.min.js">//cdnjs.cloudflare.com/ajax/libs/velocity/2.0.3/velocity.min.js</a>_x000D_
_x000D_
<div id="vue-selector">_x000D_
<div>Question 01</div>_x000D_
<input v-model="answerText" placeholder="answer me">_x000D_
<button @click="answerQuestion(0)"> Answer </button>_x000D_
_x000D_
<transition name="slide-fade" mode="in-out">_x000D_
<div v-if="answer.text === 'hello'">_x000D_
Do something A_x000D_
</div>_x000D_
<div v-else-if="answer.text === 'hihi'">_x000D_
Do something B_x000D_
</div>_x000D_
<div v-else>_x000D_
Waiting for answer_x000D_
</div>_x000D_
</transition>_x000D_
</div>
_x000D_
_x000D_
x000D