Vue单文件学习项目综合案例Demo,黑马vue教程

前言

  • 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">总价&nbsp;&nbsp;:&nbsp;&nbsp;¥&nbsp;<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>

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
清凉一夏 来点一杯星巴克吧! 当我们还在家中吹着空调敲着代码吃着西瓜的时候,可能你的她还在炎炎夏日下大汗淋漓,打开这个小程序,为她点上一杯冰镇的星巴克,后续的故事就不用再说了把,作为还在起跑线上的全栈的学习者,初试微信小程序,花了四天左右的时间初步的完成了这个小程序,这个小程序吸引我的真的就是颜啊(身为颜控的我),有木有觉得很美观,下面我们就一起看下这个demo吧 如果各位看官觉得还行不妨点个赞哦项目源码: GitHub 求小星星鼓励项目工具及文档1.微信web开发者工具:微信小程序官网 一款很好用的小程序编辑软件2.开发文档:微信小程序必备无敌文档 你想要的都在里面页面注册 app.json {"pages":[    "pages/index/index",     星巴克用星说 主页    "pages/detail/detail",   @all 我想对你们说    "pages/giftcard/giftcard", 礼品卡详情页 ], }项目功能已实现的功能scroll-view等基础事件tab切换及其高亮事件添加购物车的显示隐藏功能付款的显示隐藏及其高亮的功能未实现的功能门店列表(显示最近30家门店)功能地图定位功能具体功能预览1.tab切换在tab切换上,做到了大图切换和小图高亮,是不是效果还不错具体效果图:如下 这里底部闪光是因为录屏软件的问题哦_实现代码:如下                                   选择卡面                                                                                                                                                                                             使用点击事件就可以实现这些功能啦,有没有很简 2.giftcard在点击左边一部分的时候是跳转礼品卡详情3.购物付款功能在点击右边部分的➕和➖就会修改对应的数量了,当然哦,下面的结账也会显示你所购买的数量和总价哦,是不是觉得符合现代化简约美呀这是这个小程序最闪光点也最需要思考的地方啦,仔细一看发现是不是操作后有很多小的变化,也是这小小的变化让整个小程序更美观了这是选择礼品的布局样式             <tex

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值