文章目录
- 前言
- 一、小黑记事本
- 二、购物车
- 三、小黑记账清单
前言
- bilibili视频地址
一、小黑记事本
-
效果图
-
主代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="./css/index.css"/>
<title>记事本</title>
</head>
<body>
<!-- 主体区域 -->
<section id="app">
<!-- 输入框 -->
<header class="header">
<h1>小黑记事本</h1>
<input placeholder="请输入任务" v-model="inputTask" class="new-todo"/>
<button class="add" @click="addTask()">添加任务</button>
</header>
<!-- 列表区域 -->
<section class="main">
<ul class="todo-list" v-for="(item,index) in list" :key="item.id">
<li class="todo">
<div class="view">
<span class="index">{{ index + 1 }}</span> <label>{{ item.name }}</label>
<button class="destroy" @click="delTask(item.id)"></button>
</div>
</li>
</ul>
</section>
<!-- 统计和清空 -->
<footer class="footer" v-show="list.length > 0">
<!-- 统计 -->
<span class="todo-count">合 计:<strong> {{ list.length }} </strong></span>
<!-- 清空 -->
<button class="clear-completed" @click="clearAll()">
清空任务
</button>
</footer>
</section>
<!-- 底部 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
list: [
{id: 2, name: "我要吃饭"},
{id: 1, name: "我要睡觉"}
],
inputTask: ""
},
methods: {
addTask() {
let tempId;
//生成一个不重复的id
if (this.list[0] != null) {
tempId = this.list[0].id + 1
} else {
tempId = 1
}
this.list.unshift({
id: tempId,
name: this.inputTask
});
this.inputTask = ""
},
delTask(id) {
this.list = this.list.filter(item => item.id != id);
},
clearAll() {
this.list = [];
}
}
})
</script>
</body>
</html>
二、购物车
-
效果图
-
主代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./css/inputnumber.css" />
<link rel="stylesheet" href="./css/index.css" />
<title>购物车</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div class="app-container" id="app">
<!-- 顶部banner -->
<div class="banner-box"><img src="img/fruit.jpg" alt="" /></div>
<!-- 面包屑 -->
<div class="breadcrumb">
<span>🏠</span>
/
<span>购物车</span>
</div>
<!-- 购物车主体 -->
<div class="main" v-if="fruitList.length > 0">
<div class="table">
<!-- 头部 -->
<div class="thead">
<div class="tr">
<div class="th">选中</div>
<div class="th th-pic">图片</div>
<div class="th">单价</div>
<div class="th num-th">个数</div>
<div class="th">小计</div>
<div class="th">操作</div>
</div>
</div>
<!-- 身体 -->
<div class="tbody">
<div class="tr" :class="{ active:item.isChecked}" v-for="(item,index) in fruitList" :key="item.id" >
<div class="td"><input type="checkbox" v-model="item.isChecked" /></div>
<div class="td"><img :src="item.icon" alt="" /></div>
<div class="td">{{ item.price }}</div>
<div class="td">
<div class="my-input-number">
<button class="decrease" @click="sub(item.id)"> - </button>
<span class="my-input__inner">{{ item.num }}</span>
<button class="increase" @click="add(item.id)"> + </button>
</div>
</div>
<div class="td">{{ item.price*item.num }}</div>
<div class="td"><button @click="del(item.id)">删除</button></div>
</div>
</div>
</div>
<!-- 底部 -->
<div class="bottom">
<!-- 全选 -->
<label class="check-all">
<input type="checkbox" v-model="isAll" />
全选
</label>
<div class="right-box">
<!-- 所有商品总价 -->
<span class="price-box">总价 : ¥ <span class="price">{{ totalPrice }}</span></span>
<!-- 结算按钮 -->
<button class="pay">结算( {{ totalCount }} )</button>
</div>
</div>
</div>
<!-- 空车 -->
<div class="empty" v-else>🛒空空如也</div>
</div>
<script>
const defaultFruitList = [
{
id: 1,
icon: 'img/火龙果.png',
isChecked: true,
num: 2,
price: 6,
},
{
id: 2,
icon: 'img/荔枝.png',
isChecked: false,
num: 7,
price: 20,
},
{
id: 3,
icon: 'img/榴莲.png',
isChecked: false,
num: 3,
price: 40,
},
{
id: 4,
icon: 'img/鸭梨.png',
isChecked: true,
num: 10,
price: 3,
},
{
id: 5,
icon: 'img/樱桃.png',
isChecked: false,
num: 20,
price: 34,
},
]
const app = new Vue({
el: '#app',
data: {
// 水果列表
fruitList: JSON.parse(localStorage.getItem("list")) || defaultFruitList
// fruitList: defaultFruitList
},
computed: {
isAll: {
get() {
return this.fruitList.every(item => item.isChecked);
},
set(value) {
this.fruitList.forEach(item => item.isChecked = value);
}
},
//计算选中的总数
totalCount(){
let count=this.fruitList.reduce((sum,item)=>{
if (item.isChecked){
sum+=item.num
}
return sum;
},0)
return count;
},
//计算选中的价格
totalPrice(){
let count=this.fruitList.reduce((sum,item)=>{
if (item.isChecked){
sum+=item.num*item.price
}
return sum;
},0)
return count;
}
},
methods: {
del(id) {
this.fruitList = this.fruitList.filter(item => item.id != id);
},
sub(id) {
const fruit = this.fruitList.find(item => item.id == id);
fruit.num--;
//数量为0,删除商品
if (fruit.num == 0) {
this.del(id)
}
},
add(id) {
const fruit = this.fruitList.find(item => item.id == id);
fruit.num++
}
},
watch: {
fruitList:{
deep:true,
handler (newValue) {
//当被删完的时候置空,方便初始化数据
if (newValue.length == 0) {
newValue=null
}
//需要将变化后的数据存入本地(转JSON)
localStorage.setItem("list", JSON.stringify(newValue))
}
}
}
})
</script>
</body>
</html>
三、小黑记账清单
- 效果图
- 主代码
<!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">
<input type="text" class="form-control" placeholder="消费名称" v-model.trim="name" />
<input type="text" class="form-control" placeholder="消费价格" v-model.number="price"/>
<button type="button" class="btn btn-primary" @click="add()">添加账单</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 href="javascript:;" @click="del(item.id)">删除</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="../common/js/echarts.min.js"></script>
<script src="../common/js/vue.js"></script>
<script src="../common/js/axios.js"></script>
<script>
/**
* 接口文档地址:
* https://www.apifox.cn/apidoc/shared-24459455-ebb1-4fdc-8df8-0aff8dc317a8/api-53371058
*
* 功能需求:
* 1. 基本渲染
* 2. 添加功能
* 3. 删除功能
* 4. 饼图渲染
*/
const app = new Vue({
el: '#app',
data: {
list:[],
name:'',
price:'',
},
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}))
}
]
});
},
async add(){
if (!this.name){
alert("请输入消费名称")
return
}
if (typeof this.price !== 'number'){
alert("请输入正确的消费价格")
return
}
let param={
creator: '小黑',
name:this.name,
price:this.price
};
const res = await axios.post("https://applet-base-api-t.itheima.net/bill",param);
console.log(res)
this.getList();
this.name=''
this.price=''
},
async del(id){
const res=await axios.delete("https://applet-base-api-t.itheima.net/bill/"+id);
this.getList();
}
},
created() {
this.getList()
},
mounted(){
option = {
title: {
text: '消费账单列表',
subtext: '',
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)'
}
}
}
]
};
// 基于准备好的dom,初始化echarts实例
this.myChart = echarts.init(document.getElementById('main'));
// 绘制图表
this.myChart.setOption(option);
},
computed:{
totalPrice(){return this.list.reduce((sum,item)=>sum+=item.price,0)}
}
})
</script>
</body>
</html>