前言
Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架。它的设计目标是通过采用易于上手的结构和强大的功能,使前端开发变得更加简便和高效。以下是 Vue.js 的一些关键特性和优点:
核心特性
- 声明式渲染
- Vue.js 使用声明式语法来描述用户界面,数据和视图是双向绑定的。当数据变化时,视图会自动更新。
- 组件系统
- Vue.js 提供了一个灵活的组件系统,允许开发者将 UI 分解成可复用的组件,每个组件都有自己的逻辑和样式。
- 单文件组件 (SFC)
- Vue.js 允许开发者将 HTML、CSS 和 JavaScript 放在同一个
.vue
文件中,这样可以更容易地管理组件。
- 虚拟 DOM
- Vue.js 使用虚拟 DOM 来优化更新过程,通过最小化实际 DOM 操作来提高性能。
- 反应式数据绑定
- Vue.js 提供了响应式的数据绑定系统,使得数据与 DOM 之间的同步变得简单和高效。
- 指令
- Vue.js 提供了一组内置指令(如
v-bind
、v-model
和v-for
),帮助开发者轻松地操作 DOM。
优点
- 易于上手
- Vue.js 的学习曲线较低,适合新手入门,并且文档详细、社区活跃。
- 灵活性
- Vue.js 可以与现有项目集成,也可以用于构建复杂的单页面应用(SPA)。
- 性能高效
- 得益于虚拟 DOM 和响应式系统,Vue.js 在处理大量数据更新时表现出色。
- 生态系统
- Vue.js 拥有丰富的生态系统,包括 Vue Router、Vuex、Vue CLI 等工具和库,支持开发者在不同场景下使用。
- 强大的社区支持
- Vue.js 有一个全球活跃的社区,提供了大量的插件、教程和支持资源。
知识点
1. 创建 Vue 实例
2. v-bind 数据绑定
3. @click 点击事件绑定
4. v-show 显示或隐藏元素
知识点
* 1. 基本渲染 * (1) 立刻发送请求获取数据 created * (2) 拿到数据,存到data的响应式数据中 * (3) 结合数据,进行渲染 v-for * (4) 消费统计 => 计算属性 * 2. 添加功能 * (1) 收集表单数据 v-model * (2) 添加点击事件发送请求 * (3) 重新渲染 * 3. 删除功能 * (1) 注册点击事件,传参 id * (2) 根据 id 发送删除请求 * (3) 需要重新渲染 * 4. 饼图渲染 * (1) 初始化饼图 echarts * (2) 根据数据实时更新饼图 */
项目效果
因为接口是公用,所以这里没数据被别人删完了
源代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <!-- CSS only --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" /> <style> .red { color: red!important; } .search { width: 300px; margin: 20px 0; } .my-form { display: flex; margin: 20px 0; } .my-form input { flex: 1; margin-right: 20px; } .table > :not(:first-child) { border-top: none; } .contain { display: flex; padding: 10px; } .list-box { flex: 1; padding: 0 30px; } .list-box a { text-decoration: none; } .echarts-box { width: 600px; height: 400px; padding: 30px; margin: 0 auto; border: 1px solid #ccc; } tfoot { font-weight: bold; } @media screen and (max-width: 1000px) { .contain { flex-wrap: wrap; } .list-box { width: 100%; } .echarts-box { margin-top: 30px; } } </style> </head> <body> <div id="app"> <div class="contain"> <!-- 左侧列表 --> <div class="list-box"> <!-- 添加资产 --> <form class="my-form"> <!-- 绑定数据,trim 去掉首尾空格 number 传数字 --> <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> <!-- v-for 循环渲染数据 --> <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> <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <script> /** * 接口文档地址: * https://www.apifox.cn/apidoc/shared-24459455-ebb1-4fdc-8df8-0aff8dc317a8/api-53371058 * * 功能需求: * 1. 基本渲染 * (1) 立刻发送请求获取数据 created * (2) 拿到数据,存到data的响应式数据中 * (3) 结合数据,进行渲染 v-for * (4) 消费统计 => 计算属性 * 2. 添加功能 * (1) 收集表单数据 v-model * (2) 添加点击事件发送请求 * (3) 重新渲染 * 3. 删除功能 * (1) 注册点击事件,传参 id * (2) 根据 id 发送删除请求 * (3) 需要重新渲染 * 4. 饼图渲染 * (1) 初始化饼图 echarts * (2) 根据数据实时更新饼图 */ const app = new Vue({ el: '#app', data: { list: [], name: "", price: "" }, computed: { totalPrice () { // reduce 方法接收两个参数:一个回调函数和一个初始值。 // 回调函数接收两个参数:sum(累加器)和 item(当前项)。 // 回调函数的返回值将作为下一次调用的 sum 参数。 // 初始值是 0,表示累加开始时的值。 return this.list.reduce((sum, item) => sum + item.price, 0) } }, // 在 Vue 组件中,created 钩子在实例创建之后被调用,但数据观测和事件/侦听器的设置之前 // async created():这是一个异步的生命周期钩子函数 created。 // 使用 async 关键字表示这个函数会返回一个 Promise // async created () { // // 使用 axios 发送一个 GET 请求到指定的 URL,并传递查询参数 // const res = await axios.get('https://applet-base-api-t.itheima.net/bill', { // // params 对象包含了请求的查询参数,这里传递了一个名为 creator 的参数,值为 '小黑' // params: { // creator: '小黑' // } // }) // // 将响应数据中的 data 属性赋值给组件的 list 属性。这将更新组件的响应式数据 // this.list = res.data.data // }, // 因为下面封装了所以这里直接调用即可 created () { this.getList() }, mounted () { this.myCharts = echarts.init(document.querySelector('#main')) this.myCharts.setOption({ // 大标题 title: { text: '消费账单列表', left: 'center' }, // 提示框 tooltip: { trigger: 'item' }, // 图例 legend: { orient: 'vertical', left: 'left' }, // 数据项 series: [ { name: '消费账单', 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)' } } } ] }) }, methods: { // 因为渲染要多次使用所以封装 async getList () { const res = await axios.get('https://applet-base-api-t.itheima.net/bill', { params: { creator: '小黑' } }) this.list = res.data.data // 更新图标 this.myCharts.setOption({ series: [ { data: this.list.map((item => ({ value: item.price, name: item.name }))) } ] }) }, async add () { // 判断不能为空 if (this.name === null) { alert('请输入消费名称') return } if (this.price !== 'number') { alert('请输入数字') return } // axios 发送 post 请求提交数据 const res = await axios.post('https://applet-base-api-t.itheima.net/bill', { params: { create: '小黑', name: this.name, price: this.price } }) // 重新渲染 await this.getList() // 发送完成后清空数据 this.name = '' this.price = '' }, async del (id) { // 根据 id 发送删除请求(注意返单引号) const res = await axios.delete(`https://applet-base-api-t.itheima.net/bill/${id}`) // 重新渲染 await this.getList() } } }) </script> </body> </html>