使用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>

相关推荐
十一吖i10 分钟前
前端将后端返回的文件下载到本地
vue.js·elementplus
光影少年12 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
As977_13 分钟前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
susu108301891115 分钟前
vue3 css的样式如果background没有,如何覆盖有background的样式
前端·css
Ocean☾16 分钟前
前端基础-html-注册界面
前端·算法·html
Dragon Wu18 分钟前
前端 Canvas 绘画 总结
前端
CodeToGym23 分钟前
Webpack性能优化指南:从构建到部署的全方位策略
前端·webpack·性能优化
~甲壳虫24 分钟前
说说webpack中常见的Loader?解决了什么问题?
前端·webpack·node.js
~甲壳虫28 分钟前
说说webpack proxy工作原理?为什么能解决跨域
前端·webpack·node.js
Cwhat29 分钟前
前端性能优化2
前端