Vue【二】渲染数据,计算属性computed、侦听器watch的使用,成绩案例。
文章目录
前言
刚学完watch、computed我们可以在下面的小项目练一下手,后面做项目也会用到下面思路以及做题方法,涉及到filter,reduce等数组方法。
动态展示
注:文章末尾有初始化的结构,拿来用即可。
一、操作步骤
1、渲染数据
使用v-if把数组arr里面的数组渲进页面
tbody>
<tr v-for="(item,i) in list" :key="item.id">
<td>{{i+1}}</td>
<td>{{item.subject}}</td>
<td :class="{red:item.score<60}">{{item.score}}</td>
<td>{{item.date}}</td>
<td><a href="#">删除</a></td>
</tr>
</tbody>
//当数据为空的时候下面展示
<tbody v-show="!list.length">
<tr>
<td colspan="5">
<span class="none">暂无数据</span>
</td>
</tr>
</tbody>
效果图:
2、添加数据—添加按钮的实现
<div class="form-item">
<div class="label">科目:</div>
<div class="input">
<input type="text" placeholder="请输入科目" v-model.number="subject"/>
</div>
</div>
<div class="form-item">
<div class="label">分数:</div>
<div class="input">
<input type="text" placeholder="请输入分数" v-model.number="score"/>
</div>
</div>
<div class="form-item">
<div class="label"></div>
<div class="input">
<button class="submit" @click="addData">添加</button>
</div>
</div>
methods:{
addData(){
this.list.push({
id:Math.random(),
subject:this.subject,
score:this.score,
//时间我们简单点写成静态数据,也可以用第三方模块moment中的moment(date).format('YYYY-MM-DD hh:mm:ss')
date:new Date('2022/06/08 10:00:00')
})
}
}
效果:
3、删除数据—删除按钮的实现
我们删除数据的实现是使用数组过滤器filter来删选数据。
<tbody>
<tr v-for="(item,i) in list" :key="item.id">
<td>{{i+1}}</td>
<td>{{item.subject}}</td>
<td :class="{red:item.score<60}">{{item.score}}</td>
<td>{{item.date}}</td>
+ <td><a href="#" @click.prevent="delData(item.id)">删除</a></td>
</tr>
</tbody>
delData(id){
this.list=this.list.filter(item=>item.id!=id)
}
效果:
4、完善—平均分、总分的完成
使用计算属性来计算总分。
<td colspan="5">
+ <span>总分:{{getAll}}</span>
+ <span style="margin-left:50px">平均分:{{(getAll/(list.length||1)).toFixed(2)}}</span>
</td>
== 当list长度为0,就会显示NaN,所以当长度为0时,使总分0除以1结果为0==
computed:{
getAll(){
return this.list.reduce((num,item)=>num+item.score,0)
}
},
5、拓展—本地储存
data () {
return {
+ list: JSON.parse(localStorage.getItem('list')) || [],
subject: '',
score: ''
}
},
使用watch监听器来监听list的数据是否发生改变,如果改变立马存入本地。
watch:{
list:{
deep:true,
handler(){
localStorage.setItem('list',JSON.stringify(this.list))
}
}
}
二、代码
1、源码(未写之前)
<template>
<div class="score-case">
<div class="table">
<table>
<thead>
<tr>
<th>编号</th>
<th>科目</th>
<th>成绩</th>
<th>考试时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr >
<td>1</td>
<td>语文</td>
<td class="red">56</td>
<td>Tue Jun 07 2022 10:00:00 GMT+0800 (中国标准时间)</td>
<td><a href="#">删除</a></td>
</tr>
<tr >
<td>2</td>
<td>数学</td>
<td>100</td>
<td>Tue Jun 07 2022 10:00:00 GMT+0800 (中国标准时间)</td>
<td><a href="#">删除</a></td>
</tr>
</tbody>
<!-- <tbody >
<tr>
<td colspan="5">
<span class="none">暂无数据</span>
</td>
</tr>
</tbody> -->
<tfoot>
<tr>
<td colspan="5">
<span>总分:321</span>
<span style="margin-left:50px">平均分:80.25</span>
</td>
</tr>
</tfoot>
</table>
</div>
<div class="form">
<div class="form-item">
<div class="label">科目:</div>
<div class="input">
<input type="text" placeholder="请输入科目" />
</div>
</div>
<div class="form-item">
<div class="label">分数:</div>
<div class="input">
<input type="text" placeholder="请输入分数" />
</div>
</div>
<div class="form-item">
<div class="label"></div>
<div class="input">
<button class="submit" >添加</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'ScoreCase',
data () {
return {
list: [
{id: 15, subject: '语文', score: 89, date: new Date('2022/06/07 10:00:00')},
{id: 27, subject: '数学', score: 100, date: new Date('2022/06/07 15:00:00')},
{id: 32, subject: '英语', score: 56, date: new Date('2022/06/08 10:00:00')},
{id: 41, subject: '物理', score: 76, date: new Date('2022/06/08 10:00:00')}
],
subject: '',
score: ''
}
}
};
</script>
<style lang="less">
.score-case {
width: 1000px;
margin: 50px auto;
display: flex;
.table {
flex: 4;
table {
width: 100%;
border-spacing: 0;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
th {
background: #f5f5f5;
}
tr:hover td {
background: #f5f5f5;
}
td,
th {
border-bottom: 1px solid #ccc;
border-right: 1px solid #ccc;
text-align: center;
padding: 10px;
&.red {
color: red;
}
}
}
.none {
height: 100px;
line-height: 100px;
color: #999;
}
}
.form {
flex: 1;
padding: 20px;
.form-item {
display: flex;
margin-bottom: 20px;
align-items: center;
}
.form-item .label {
width: 60px;
text-align: right;
font-size: 14px;
}
.form-item .input {
flex: 1;
}
.form-item input,
.form-item select {
appearance: none;
outline: none;
border: 1px solid #ccc;
width: 200px;
height: 40px;
box-sizing: border-box;
padding: 10px;
color: #666;
}
.form-item input::placeholder {
color: #666;
}
.form-item .cancel,
.form-item .submit {
appearance: none;
outline: none;
border: 1px solid #ccc;
border-radius: 4px;
padding: 4px 10px;
margin-right: 10px;
font-size: 12px;
background: #ccc;
}
.form-item .submit {
border-color: #069;
background: #069;
color: #fff;
}
}
}
</style>
2、源码(已经完成)
<template>
<div class="score-case">
<div class="table">
<table>
<thead>
<tr>
<th>编号</th>
<th>科目</th>
<th>成绩</th>
<th>考试时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,i) in list" :key="item.id">
<td>{{i+1}}</td>
<td>{{item.subject}}</td>
<td :class="{red:item.score<60}">{{item.score}}</td>
<td>{{item.date}}</td>
<td><a href="#" @click.prevent="delData(item.id)">删除</a></td>
</tr>
</tbody>
<tbody v-show="!list.length">
<tr>
<td colspan="5">
<span class="none">暂无数据</span>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5">
<span>总分:{{getAll}}</span>
<span style="margin-left:50px">平均分:{{(getAll/(list.length||1)).toFixed(2)}}</span>
</td>
</tr>
</tfoot>
</table>
</div>
<div class="form">
<div class="form-item">
<div class="label">科目:</div>
<div class="input">
<input type="text" placeholder="请输入科目" v-model.number="subject"/>
</div>
</div>
<div class="form-item">
<div class="label">分数:</div>
<div class="input">
<input type="text" placeholder="请输入分数" v-model.number="score"/>
</div>
</div>
<div class="form-item">
<div class="label"></div>
<div class="input">
<button class="submit" @click="addData">添加</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'ScoreCase',
data () {
return {
list: [
{id: 15, subject: '语文', score: 89, date: new Date('2022/06/07 10:00:00')},
{id: 27, subject: '数学', score: 100, date: new Date('2022/06/07 15:00:00')},
{id: 32, subject: '英语', score: 56, date: new Date('2022/06/08 10:00:00')},
{id: 41, subject: '物理', score: 76, date: new Date('2022/06/08 10:00:00')}
],
subject: '',
score: ''
}
},
methods:{
addData(){
this.list.push({
id:Math.random(),
subject:this.subject,
score:this.score,
//时间我们简单点写成静态数据,也可以用第三方模块moment中的moment(date).format('YYYY-MM-DD hh:mm:ss')
date:new Date('2022/06/08 10:00:00')
})
this.subject=this.score=''
},
delData(id){
this.list=this.list.filter(item=>item.id!=id)
}
},
computed:{
getAll(){
return this.list.reduce((num,item)=>num+item.score,0)
}
},
};
</script>
<style lang="less">
.score-case {
width: 1000px;
margin: 50px auto;
display: flex;
.table {
flex: 4;
table {
width: 100%;
border-spacing: 0;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
th {
background: #f5f5f5;
}
tr:hover td {
background: #f5f5f5;
}
td,
th {
border-bottom: 1px solid #ccc;
border-right: 1px solid #ccc;
text-align: center;
padding: 10px;
&.red {
color: red;
}
}
}
.none {
height: 100px;
line-height: 100px;
color: #999;
}
}
.form {
flex: 1;
padding: 20px;
.form-item {
display: flex;
margin-bottom: 20px;
align-items: center;
}
.form-item .label {
width: 60px;
text-align: right;
font-size: 14px;
}
.form-item .input {
flex: 1;
}
.form-item input,
.form-item select {
appearance: none;
outline: none;
border: 1px solid #ccc;
width: 200px;
height: 40px;
box-sizing: border-box;
padding: 10px;
color: #666;
}
.form-item input::placeholder {
color: #666;
}
.form-item .cancel,
.form-item .submit {
appearance: none;
outline: none;
border: 1px solid #ccc;
border-radius: 4px;
padding: 4px 10px;
margin-right: 10px;
font-size: 12px;
background: #ccc;
}
.form-item .submit {
border-color: #069;
background: #069;
color: #fff;
}
}
}
</style>