编号 | 消费名称 | 消费价格 | 操作 |
---|---|---|---|
{{index+1}} | {{item.name}} | {{item.price.toFixed(2)}} | 删除 |
消费总计: {{totalPrice}} |
案例-小黑记账清单#
功能需求:
- 基本渲染
- 添加功能
- 删除功能
- 饼图渲染
基本渲染#
-
立即发送请求获取数据
created
- 拿到数据,存入data
-
结合数据,进行渲染
v-for
- 消费统计:计算属性
<tbody>
<tr v-for="(item, index) in list" :key="item.id">
<td>{{index+1}}</td>
<td>{{item.name}}</td>
<td :class="{red:item.price>=500}">{{item.price.toFixed(2)}}</td>
<td><a href="javascript:;">删除</a></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="4">消费总计: {{totalPrice}}</td>
</tr>
</tfoot>
const app = new Vue({
el: '#app',
data: {
list: [],
},
computed: {
totalPrice() {
return this.list.reduce((sum, item) => sum + item.price, 0).toFixed(2);
},
},
async created() {
const res = await axios.get('https://applet-base-api-t.itheima.net/bill', {
params: {
creator: 'cfe',
},
});
console.log(res);
this.list = res.data.data;
},
});
添加功能#
-
收集表单数据
v-model
- 给添加按钮注册点击事件,发送添加请求
- 需要重新渲染
v-model
绑定数据
按钮注册点击事件
<input v-model.trim="name" type="text" class="form-control" placeholder="消费名称" />
<input v-model.number="price" type="text" class="form-control" placeholder="消费价格" />
<button @click="add" type="button" class="btn btn-primary">添加账单</button>
渲染功能常用,所以封装起来
const app = new Vue({
el: '#app',
data: {
list: [],
name: '',
price: '',
},
computed: {
totalPrice() {
return this.list.reduce((sum, item) => sum + item.price, 0).toFixed(2);
},
},
created() {
this.getList();
},
methods: {
async getList() {
const res = await axios.get('https://applet-base-api-t.itheima.net/bill', {
params: {
creator: 'cfe',
},
});
console.log(res);
this.list = res.data.data;
},
async add() {
if (!this.name) {
alert('请输入消费项');
return;
}
if (typeof this.price !== 'number') {
alert('请输入正确的消费价格');
return;
}
// 发送添加请求
const res = await axios.post('https://applet-base-api-t.itheima.net/bill', {
creator: 'cfe',
name: this.name,
price: this.price,
});
console.log(res);
// 重新渲染
this.getList();
this.name = '';
this.price = '';
},
},
});
删除功能#
- 注册点击事件,传参id
- 根据id发送删除请求
- 需要重新渲染
<td><a @click="del(item.id)" href="javascript:;">删除</a></td>
methods: {
// ...
async del(id) {
const res = await axios.delete(`https://applet-base-api-t.itheima.net/bill/${id}`);
this.getList();
},
},
饼图渲染#
-
初始化一个饼图
echarts.init(dom)
,饼图初始化需要等dom加载完成,所以使用mounted钩子实现 - 根据数据实时更新饼图
<!-- 右侧图表 -->
<div class="echarts-box" id="main"></div>
由于饼图数据需要使用动态的,所以按照echarts官方说法
异步数据的加载与动态更新
,设置好样式后,异步加载的数据通过
setOption
重新设置即可(只需设置需修改的数据)
mounted() {
// getList不能直接访问mounted中的myChart,所以把myChart挂载到实例上,以便于加载异步数据
this.myChart = echarts.init(document.querySelector('#main'));
let option = {
title: {
// 大标题
text: '消费账单列表',
left: 'center',
top: '15%',
},
tooltip: {
// 提示框
trigger: 'item',
},
legend: {
// 图例
itemWidth: 15,
textStyle: {
fontSize: 10,
},
},
series: [
{
name: '消费账单',
type: 'pie',
radius: '50%',
top: '20%',
data: [
// 图表数据需要动态数据
// { value: 1048, name: 'Search Engine' },
// { value: 735, name: 'Direct' },
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
},
},
],
};
this.myChart.setOption(option);
},
methods: {
async getList() {
const res = await axios.get('https://applet-base-api-t.itheima.net/bill', {
params: {
creator: 'cfe',
},
});
console.log(res);
this.list = res.data.data;
// 更新图表,通过setOption重设data
this.myChart.setOption({
// 数据项
series: [
{
// 通过map将list中的图表所需数据转换为渲染所需的格式
data: this.list.map(item => ({ value: item.price, name: item.name })),
},
],
});
},
},