Vue.js. Переменная в свойстве data обновляется только по третьему клику
У меня есть виджет. Логика работы: при выборе радио кнопки в блоке появляется следующий блок.
Мне нужно сделать, чтобы при изменении радио кнопки в блоке, все остальные блоки (кроме одного, следующего за данным) скрывались. Все работает, кроме одного момента: cкрытие блоков проиcходит только после второго изменения радио кнопки. Не могу понять почему так работает.
При клике на радио я отслеживаю изменение заголовка, при этом изменяется переменная queustionIndex и подгружается следующий блок. Но вот при изменении чекбокса эта переманная обновляется не с первого раза. Я ее вывел в консоль, в первом блоке. Спасибо за помощь.
https://jsfiddle.net/IvanGrishov/fsc3ea4j/13/
var quiz = {
questions: [
{
text: "Выберите год выпуска",
newText: "Поколение",
name: 'generation',
responses: [
{
value: '(1981 - 1986)',
},
{
value: '(1986 - 1994)',
},
{
value: '(1996 - 2002)',
}
],
checkedName: '',
},
{
text: "Выберите тип кузова",
newText: "Тип кузова",
name: 'body',
responses: [
{
value: 'Купе',
},
{
value: 'Универсал',
},
],
checkedName: '',
},
{
text: "Выберите коробку передач",
newText: "Коробка передач",
name: 'transmission',
responses: [
{
value: 'Ручная',
},
{
value: 'Автоматическая',
},
{
value: 'Роботизированная',
},
{
value: 'Вариативная',
},
],
checkedName: '',
},
{
text: "Выберите двигатель",
newText: "Двигатель",
name: 'engine',
responses: [
{
value: 'Я не знаю модификации',
},
{
value: '1.0 MT (50 л.с.)',
},
],
checkedName: '',
},
]
}
new Vue({
el: '#app',
data: {
quiz: quiz,
questionIndex: 0,
userResponses: Array(),
},
computed: {
bToWatchGeneration: function() {
return quiz.questions[0].checkedName
},
bToWatchBody: function() {
return quiz.questions[1].checkedName
},
bToWatchTransmission: function() {
return quiz.questions[2].checkedName
},
bToWatchEngine: function() {
return quiz.questions[3].checkedName
},
},
watch: {
bToWatchGeneration: function() {
///// обновление количества табов с параметрами
console.log(this.questionIndex)
this.questionIndex = 1
/// очистка параметров
for (let i = 1; i < this.quiz.questions.length; i++) {
if (this.quiz.questions[i].checkedName != '') {
this.quiz.questions[i].checkedName = ''
}
}
},
bToWatchBody: function() {
///// обновление количества табов с параметрами
this.questionIndex = 2
/// очистка параметров
for (let i = 2; i < this.quiz.questions.length; i++) {
if (this.quiz.questions[i].checkedName != '') {
this.quiz.questions[i].checkedName = ''
}
}
},
bToWatchTransmission: function() {
///// обновление количества табов с параметрами
this.questionIndex = 3
/// очистка параметров
for (let i = 3; i < this.quiz.questions.length; i++) {
if (this.quiz.questions[i].checkedName != '') {
this.quiz.questions[i].checkedName = ''
}
}
},
bToWatchEngine: function() {
///// обновление количества табов с параметрами
this.questionIndex = 4
/// очистка параметров
for (let i = 4; i < this.quiz.questions.length; i++) {
if (this.quiz.questions[i].checkedName != '') {
this.quiz.questions[i].checkedName = ''
}
}
},
}
})
.form__body-block {
display: flex;
flex-direction: column;
}
.choice {
margin-top: 20px;
}
#app {
display: flex;
margin-left: 100px;
flex-direction: column;
}
.form__body--title-wrap {
margin-bottom: 10px;
}
.radio-wrapper {
margin-bottom: 5px;
}
.form__body--subtitle {
display: block;
}
.choice_inner {
background-color: #8E44AD;
color: #fff;
border-radius: 8px;
padding: 15px;
}
.choice {
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.6/vue.js"></script>
<div id="app">
<div class="choice" v-for="(question, index) in quiz.questions" v-bind:key="index">
<div class="choice_inner" v-show="index <= questionIndex">
<div class="form__body--title">
<div class="form__body--title-wrap" v-bind:class="{ title__new: question.checkedName}">
{{ question.checkedName ? question.newText : question.text }}
<span class="form__body--subtitle">{{ question.checkedName }}</span>
</div>
<div class="form__body-block">
<label class="radio-wrapper"
v-for="response in question.responses">
<input type="radio"
v-bind:value="response.value"
v-bind:name="question.name"
v-model="question.checkedName">
<span class="radio-text">{{ response.value }}</span>
</label>
</div>
</div>
</div>
</div>
</div>
Ответы (1 шт):
Помогли на хабре. this.quiz.questions[i].checkedName = '' В этот момент срабатывает событие watch и в очередь ставится следующий обработчик. Можно перенести this.questionIndex = 1 в конец функции, но лучше проверять новое значение и ничего не делать, если оно пустое.
https://jsfiddle.net/73xcrau4/
var quiz = {
questions: [
{
text: "Выберите год выпуска",
newText: "Поколение",
name: 'generation',
responses: [
{
value: '(1981 - 1986)',
},
{
value: '(1986 - 1994)',
},
{
value: '(1996 - 2002)',
}
],
checkedName: '',
},
{
text: "Выберите тип кузова",
newText: "Тип кузова",
name: 'body',
responses: [
{
value: 'Купе',
},
{
value: 'Универсал',
},
],
checkedName: '',
},
{
text: "Выберите коробку передач",
newText: "Коробка передач",
name: 'transmission',
responses: [
{
value: 'Ручная',
},
{
value: 'Автоматическая',
},
{
value: 'Роботизированная',
},
{
value: 'Вариативная',
},
],
checkedName: '',
},
{
text: "Выберите двигатель",
newText: "Двигатель",
name: 'engine',
responses: [
{
value: 'Я не знаю модификации',
},
{
value: '1.0 MT (50 л.с.)',
},
],
checkedName: '',
},
]
}
new Vue({
el: '#app',
data: {
quiz: quiz,
questionIndex: 0,
userResponses: Array(),
},
computed: {
bToWatchGeneration: function() {
return quiz.questions[0].checkedName
},
bToWatchBody: function() {
return quiz.questions[1].checkedName
},
bToWatchTransmission: function() {
return quiz.questions[2].checkedName
},
bToWatchEngine: function() {
return quiz.questions[3].checkedName
},
},
watch: {
bToWatchGeneration: function() {
///// обновление количества табов с параметрами
this.questionIndex = 1
/// очистка параметров
for (let i = 1; i < this.quiz.questions.length; i++) {
if (this.quiz.questions[i].checkedName != '') {
this.quiz.questions[i].checkedName = ''
}
}
},
bToWatchBody: function() {
if (this.bToWatchBody === '') {
return;
}
///// обновление количества табов с параметрами
this.questionIndex = 2
/// очистка параметров
for (let i = 2; i < this.quiz.questions.length; i++) {
if (this.quiz.questions[i].checkedName != '') {
this.quiz.questions[i].checkedName = ''
}
}
},
bToWatchTransmission: function() {
if (this.bToWatchTransmission === '') {
return;
}
///// обновление количества табов с параметрами
this.questionIndex = 3
/// очистка параметров
for (let i = 3; i < this.quiz.questions.length; i++) {
if (this.quiz.questions[i].checkedName != '') {
this.quiz.questions[i].checkedName = ''
}
}
},
bToWatchEngine: function() {
if (this.bToWatchEngine === '') {
return;
}
///// обновление количества табов с параметрами
this.questionIndex = 4
/// очистка параметров
for (let i = 4; i < this.quiz.questions.length; i++) {
if (this.quiz.questions[i].checkedName != '') {
this.quiz.questions[i].checkedName = ''
}
}
},
}
})
.form__body-block {
display: flex;
flex-direction: column;
}
.choice {
margin-top: 20px;
}
#app {
display: flex;
margin-left: 100px;
flex-direction: column;
}
.form__body--title-wrap {
margin-bottom: 10px;
}
.radio-wrapper {
margin-bottom: 5px;
}
.form__body--subtitle {
display: block;
}
.choice_inner {
background-color: #8E44AD;
color: #fff;
border-radius: 8px;
padding: 15px;
}
.choice {
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.6/vue.js"></script>
<div id="app">
<div class="choice" v-for="(question, index) in quiz.questions" v-bind:key="index">
<div class="choice_inner" v-show="index <= questionIndex">
<div class="form__body--title">
<div class="form__body--title-wrap" v-bind:class="{ title__new: question.checkedName}">
{{ question.checkedName ? question.newText : question.text }}
<span class="form__body--subtitle">{{ question.checkedName }}</span>
</div>
<div class="form__body-block">
<label class="radio-wrapper"
v-for="response in question.responses">
<input type="radio"
v-bind:value="response.value"
v-bind:name="question.name"
v-model="question.checkedName">
<span class="radio-text">{{ response.value }}</span>
</label>
</div>
</div>
</div>
</div>
</div>