使用Vue实现记账清单和数据可视化图标渲染

记账清单和图标渲染

功能需求:
  1. 基本渲染

    ​ * (1) 立刻发送请求获取数据 created

    ​ * (2) 拿到数据,存到data的响应式数据中

    ​ * (3) 结合数据,进行渲染 v-for

    ​ * (4) 消费统计 => 计算属性

  2. 添加功能

    ​ * (1) 收集表单数据 v-model

    ​ * (2) 给添加按钮注册点击事件,发送添加请求

    ​ * (3) 需要重新渲染

  3. 删除功能

    ​ * (1) 注册点击事件,传参传 id

    ​ * (2) 根据 id 发送删除请求

    ​ * (3) 需要重新渲染

  4. 饼图渲染

    ​ * (1) 初始化一个饼图 echarts.init(dom) mounted钩子实现

    ​ * (2) 根据数据实时更新饼图 echarts.setOption({ ... })



项目代码

容器视图代码

html 复制代码
  <div id="app">
    <div class="contain">
      <!-- 左侧列表 -->
      <div class="list-box">

        <!-- 添加资产 -->
        <form class="my-form">
          <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>
        </form>

        <table class="table table-hover">
          <thead>
            <tr>
              <th>编号</th>
              <th>消费名称</th>
              <th>消费价格</th>
              <th>操作</th>
            </tr>
          </thead>
          <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 @click="del(item.id)" href="javascript:;">删除</a></td>
            </tr>
          </tbody>
          <tfoot>
            <tr>
              <td colspan="4">消费总计: {{ totalPrice.toFixed(2) }}</td>
            </tr>
          </tfoot>
        </table>
      </div>

      <!-- 右侧图表 -->
      <div class="echarts-box" id="main"></div>
    </div>
  </div>

Vue实例代码

javascript 复制代码
    const app = new Vue({
      el: '#app',
      data: {
        list: [],
        name: '',
        price: ''
      },

      // 计算属性
      computed: {
        totalPrice() {
          return this.list.reduce((sum, item) => sum + item.price, 0)
        }
      },
      // 1、渲染
      created() {
        this.getList()
      },
      //自己封装的方法。
      methods: {
        // 封装渲染函数
        async getList() {
          // 发送渲染请求,获取数据
          const res = await axios.get('https://applet-base-api-t.itheima.net/bill', {
            params: {
              creator: '刘不住'
            }
          })
          // 将结果赋值给实例上面的数据。
          this.list = res.data.data

          // 异步 更新图标  
          this.myChart.setOption({
            // 数据项
            series: [
              {
                data: this.list.map(item => ({ value: item.price, name: item.name }))
              }
            ]

          })
        },
        // 2、添加
        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: '刘不住',
            name: this.name,
            price: this.price
          })
          // 添加完成后,重新渲染一次
          this.getList()
          // 重置输入框
          this.name = ''
          this.price = ''
        },
        // 3、删除
        del(id) {
          // 发起删除请求
          axios.delete(`https://applet-base-api-t.itheima.net/bill/${id}`)
          // 调用渲染API
          this.getList()
          alert('删除成功')
        }
      },
      mounted() {
        // 将myChart挂载在实例上,就相当于实例中所有所用于都可以访问使用
        this.myChart = echarts.init(document.querySelector('#main'))
        // 配置项数据
        option = {
          // 标题
          title: {
            text: '消费账单列表',
            subtext: 'Fake Data',
            left: 'center'
          },
          tooltip: {
            trigger: 'item'
          },
          legend: {
            orient: '消费账单',
            left: 'left'
          },
          // 数据项
          series: [
            {
              name: 'Access From',
              type: 'pie',
              radius: '50%',
              data: [
                // { value: 1048, name: 'Search Engine' },
                // { value: 735, name: 'Direct' },
                // { value: 580, name: 'Email' },
                // { value: 484, name: 'Union Ads' },
                // { value: 300, name: 'Video Ads' }
              ],
              emphasis: {
                itemStyle: {
                  shadowBlur: 10,
                  shadowOffsetX: 0,
                  shadowColor: 'rgba(0, 0, 0, 0.5)'
                }
              }
            }
          ]
        }
        this.myChart.setOption(option)
      }
    })
  </script>

相关推荐
IT_陈寒3 分钟前
SpringBoot自动配置失灵?你可能忘了这个关键注解
前端·人工智能·后端
iCOD3R40 分钟前
Skill - kill-ai-slop 解决“AI 味”样式
前端·css·ai编程
shuaijie05181 小时前
强制修改调用接口的api地址。
javascript·vue.js·ecmascript
皮音1 小时前
Skill 在项目中的实践 —— 从 Agent 困境到 Skill 工程化
前端
大龄秃头程序员1 小时前
RN 0.86 新架构实战:TurboModule + Fabric 组件 + iOS 原生容器,完整代码开源
前端·react native
这是个栗子1 小时前
前端开发中的常用工具函数(八)
开发语言·前端·javascript
Hilaku1 小时前
Vue 和 React 真正的差距,不在语法,而在团队犯错成本
前端·javascript·程序员
研☆香2 小时前
为什么变量声明在赋值前也能使用?—— 深入理解 JavaScript 变量提升与作用域
开发语言·前端·javascript
Liora_Yvonne2 小时前
目录结构到底怎么设计?别再把 components 和 utils 当垃圾桶了
前端
柯克七七2 小时前
我把 bug 修得太干净了,测试组以为这个模块本来就没问题
前端·javascript·typescript