Vue.js:使用Computed属性的条件渲染数组



我是Vue的新手,在过去的几个小时里,我一直在研究如何在创建生日组件的实践项目的方法和计算属性中使用条件逻辑。我见过其他人在其计算属性中使用if/else语句,但收到了一条Unexpected side effect in "displayDays" computed property错误消息。

我的目标是构建这个组件,以便在通过选项列表(或者在本例中为按钮(选择每个单独的DOB元素时,返回mm/dd/yyyy格式的DOB字符串。当用户单击生日月份时,我希望该月份的日期列表在与该月份关联的模板中显示相应的日期数组。

这就是我陷入困境的地方。我最初试图在方法点击事件selectedMonth()上添加数组值,经过一番研究,我意识到我需要使用计算的属性来更改天数组中的数据,就像我想要的那样。但是,在多次尝试将if/else语句无错误地运行到计算部分之后,我不确定我缺少了什么。

非常感谢在这方面的任何帮助或指导!

以下是我的代码:

<template>
<div>
<div id="months">
<label class="uppercase">Month</label>
<label>Select a month</label>
<div>
<button
class="month"
v-for="month in months"
:key="month.text" 
:value="month.value"
v-on:click="selectedMonth(month)"
>{{ month.text }}</button>
</div>
</div>
<div id="days">
<label class="uppercase">Day</label>
<label>Select a day</label>
<div>
<button
class="day"
v-for="day in displayDays"
:key="day" 
v-on:click="selectedDay(day)"
>{{ day }}</button>
</div>
</div>
<div id="year">
<label class="uppercase">Input Year</label>
<label aria-label="Four Digit Year">Four Digit YYYY</label>
<input
type="text"
id="dobYear"
name="year"
maxlength="4"
>
</div>
<button>
Submit DOB
</button>
</div>
</template>
<script>
export default {
name: 'birthday',
data() {
return {
months: [
{text: 'Jan', value: '01'},
{text: 'Feb', value: '02'},
{text: 'Mar', value: '03'},
{text: 'Apr', value: '04'},
{text: 'May', value: '05'},
{text: 'Jun', value: '06'},
{text: 'Jul', value: '07'},
{text: 'Aug', value: '08'},
{text: 'Sep', value: '09'},
{text: 'Oct', value: '10'},
{text: 'Nov', value: '11'},
{text: 'Dec', value: '11'}
],
days: [],
year: '',
active: true,
birthday:['','','',],
}
},
methods: {
selectedMonth(month) {
// console.log('clicked '+ month);
this.birthday[0] = month.value;
this.birthday[1] = '';
console.log(this.birthday);
},
selectedDay(day) {
// console.log('clicked '+ day);
this.birthday[1] = day;
console.log(this.birthday);
this.birthDay = day;
},
submittedYear(year) {
this.birthday[2] = year;
console.log(this.birthday);
}
},
computed: {
displayDays() {
if(this.month === 'Feb') {
return this.days = ['01','02','03','04','05','06','07','08','09','10',
'11','12','13','14','15','16','17','18','19','20',
'21','22','23','24','25','26','27','28', '29']
} else if(this.month === 'Apr' || this.month === 'Jun' || this.month === 'Sep' || this.month === 'Nov') {
return this.days = ['01','02','03','04','05','06','07','08','09','10',
'11','12','13','14','15','16','17','18','19','20',
'21','22','23','24','25','26','27','28','29','30']
} else {
return this.days = ['01','02','03','04','05','06','07','08','09','10',
'11','12','13','14','15','16','17','18','19','20',
'21','22','23','24','25','26','27','28','29','30','31']
}
}
}
}
</script>
<style scoped>
#months, #days, #year {
border: 0.125rem solid #e5e5e5;
border-radius: 0.5rem;
margin-bottom: 0.625rem;
}
#months > div, #days > div, #year {
display: flex;
flex-wrap: wrap;
flex-direction: row;
gap: 0.75rem 0.4375rem;
justify-content: center;
padding: 10% 11% 10%;
box-sizing: border-box;
}
button {
text-align: center;
width: 5.0625rem;
height: 2.625rem;
background: #fff;
border-radius: 6.25rem;
border: 0.125rem solid #5500B3;
line-height: 2.4rem;
}
#days > div {
justify-content: left;
}
#days > div > button {
border-radius: 10rem;
width: 2.625rem;
}
#months > div > button:hover, #days > div > button:hover {
cursor: pointer;
background: #efefef;
}
#year input {
font-size: 1.125rem;
font-weight: 400;
border: #ececec;
box-sizing: border-box;
padding: 0.3125rem 0.875rem 0rem;
background: #ececec solid;
border-radius: 0.625rem;
height: 3.75rem;
border-style: none;
}
.uppercase {
text-transform: uppercase;
}
</style>

问题在于计算属性部分。

您不应该简单地在displayDays计算方法中为this.days分配所需的数组。相反,您必须从computed属性返回所需的数组。

此外,当计算出的属性中的任何一个参数发生变化时,将重新评估计算机属性。在这里,您在computed属性中使用this.month,但您没有在代码中的任何位置更新它,因此您的计算属性永远不会被重新计算。因此,必须将selectedMonth方法中this.month的值指定为this.month = month.text;。一旦this.month的值发生更改,将使用this.month的新值再次评估您计算的属性。

工作Fiddle

new Vue({
el: '#app',
name: 'birthday',
data() {
return {
months: [
{ text: 'Jan', value: '01' },
{ text: 'Feb', value: '02' },
{ text: 'Mar', value: '03' },
{ text: 'Apr', value: '04' },
{ text: 'May', value: '05' },
{ text: 'Jun', value: '06' },
{ text: 'Jul', value: '07' },
{ text: 'Aug', value: '08' },
{ text: 'Sep', value: '09' },
{ text: 'Oct', value: '10' },
{ text: 'Nov', value: '11' },
{ text: 'Dec', value: '11' }
],
days: [],
year: '',
active: true,
birthday: ['', '', '',],
month: null,
}
},
methods: {
selectedMonth(month) {
// console.log('clicked '+ month);
this.birthday[0] = month.value;
this.birthday[1] = '';
console.log(this.birthday);
this.month = month.text;
},
selectedDay(day) {
// console.log('clicked '+ day);
this.birthday[1] = day;
console.log(this.birthday);
this.birthDay = day;
},
submittedYear(year) {
this.birthday[2] = year;
console.log(this.birthday);
}
},
computed: {
displayDays() {
if (this.month === 'Feb') {
return ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10',
'11', '12', '13', '14', '15', '16', '17', '18', '19', '20',
'21', '22', '23', '24', '25', '26', '27', '28', '29']
} else if (this.month === 'Apr' || this.month === 'Jun' || this.month === 'Sep' || this.month === 'Nov') {
return ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10',
'11', '12', '13', '14', '15', '16', '17', '18', '19', '20',
'21', '22', '23', '24', '25', '26', '27', '28', '29', '30']
} else {
return ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10',
'11', '12', '13', '14', '15', '16', '17', '18', '19', '20',
'21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31']
}
}
}
})
#months, #days, #year {
border: 0.125rem solid #e5e5e5;
border-radius: 0.5rem;
margin-bottom: 0.625rem;
}
#months > div, #days > div, #year {
display: flex;
flex-wrap: wrap;
flex-direction: row;
gap: 0.75rem 0.4375rem;
justify-content: center;
padding: 10% 11% 10%;
box-sizing: border-box;
}
button {
text-align: center;
width: 5.0625rem;
height: 2.625rem;
background: #fff;
border-radius: 6.25rem;
border: 0.125rem solid #5500B3;
line-height: 2.4rem;
}
#days > div {
justify-content: left;
}
#days > div > button {
border-radius: 10rem;
width: 2.625rem;
}
#months > div > button:hover, #days > div > button:hover {
cursor: pointer;
background: #efefef;
}
#year input {
font-size: 1.125rem;
font-weight: 400;
border: #ececec;
box-sizing: border-box;
padding: 0.3125rem 0.875rem 0rem;
background: #ececec solid;
border-radius: 0.625rem;
height: 3.75rem;
border-style: none;
}
.uppercase {
text-transform: uppercase;
}
<script src="https://cdn.jsdelivr.net/npm/vue@^2"></script>
<div id="app">
<div>
<div id="months">
<label class="uppercase">Month</label>
<label>Select a month</label>
<div>
<button class="month" v-for="month in months" :key="month.text" :value="month.value"
v-on:click="selectedMonth(month)">{{ month.text }}</button>
</div>
</div>
<div id="days">
<label class="uppercase">Day</label>
<label>Select a day</label>
<div>
<button class="day" v-for="day in displayDays" :key="day" v-on:click="selectedDay(day)">{{ day
}}</button>
</div>
</div>
<div id="year">
<label class="uppercase">Input Year</label>
<label aria-label="Four Digit Year">Four Digit YYYY</label>
<input type="text" id="dobYear" name="year" maxlength="4">
</div>
<button>
Submit DOB
</button>
</div>
</div>

最新更新