案例-小黑记账清单

1.7k 词
案例-小黑记账清单

案例-小黑记账清单#

功能需求:

  1. 基本渲染
  2. 添加功能
  3. 删除功能
  4. 饼图渲染

基本渲染#

  1. 立即发送请求获取数据 created
  2. 拿到数据,存入data
  3. 结合数据,进行渲染 v-for
  4. 消费统计:计算属性
<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;
    },
});

添加功能#

  1. 收集表单数据 v-model
  2. 给添加按钮注册点击事件,发送添加请求
  3. 需要重新渲染

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 = '';
        },
    },
});

删除功能#

  1. 注册点击事件,传参id
  2. 根据id发送删除请求
  3. 需要重新渲染
<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();
    },
},

饼图渲染#

  1. 初始化一个饼图 echarts.init(dom) ,饼图初始化需要等dom加载完成,所以使用mounted钩子实现
  2. 根据数据实时更新饼图
  3. <!-- 右侧图表 -->
    <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 })),
                    },
                ],
            });
        },
    },