zoukankan      html  css  js  c++  java
  • Vue+Bootstrap实现购物车程序(3)

    效果展示:(说明:使用webpack重构购物车程序,使用vue-cli生成项目脚手架)

    文件结构:

    代码:

    (1)将原来编写的btn-grp组件单独编写到BtnGrp.vue文件中

    • 可以看到现在代码清晰了很多,template标签部分编写模板,script标签部分编写组件的交互代码,编写方式和原先写在HTML的代码一致

    • 现在整个前端应用都是基于组件化的,代码变得更加清晰了

    <!--vue组件-->
    <template>
        <div style="float:right;">
          <input class="form-control"
                 v-model="searchProduct"
                 @keyup.enter="filterProduct"
                 type="text"
                 placeholder="请输入商品名称"/>
        </div>
    </template>
    
    <script type="application/javascript">
    //    import App from '../App';
        export default{
          name:"BtnGroup",
          props:['products'],
          data:function(){
            return {
              searchProduct:''
            }
          },
          methods:{
            /* 商品筛选 */
            filterProduct:function(){
    //          console.log(this.$parent.products)
              var searchArr = [];
              for(let i=0;i<this.$parent.products.length;i++){
                searchArr.push(this.$parent.products[i].name)
              }
              var searchIndex = searchArr.indexOf(this.searchProduct);
              if(searchIndex !== -1){
                this.$parent.products = this.$parent.products.filter(function(element, index, self){
                  /* element数组元素、index元素索引、self数组本身 */
                  return index == searchIndex;
                })
              }else{
                alert('暂无符合商品');
              }
            }
          }
    
        }
    //    module.exports = BtnGroup;
    //    export default BtnGroup;
    //  export default {
    //    props: ['buttons']
    //  }
    </script>
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <!--翻译:添加“scoped”属性以仅将CSS限制为此组件-->
    <style type="text/css" scoped>
    
    </style>

    (2)将原来写在HTML中的代码重构到App.vue中

    • 此处因为需要用到BtnGrp组件,所以需要先import 组件,然后在components中引用该组件

    <!--主页组件-->
    
    <template>
      <div id="app" class="container">
        <h1>购物车</h1>
        <hr>
        <!--<BtnGroup v-bind:buttons="buttons"></BtnGroup>-->
        <div style="overflow: hidden">
          <div style="float: left">
            <button type="button" v-on:click="addHandler" class="btn btn-primary">添加</button>
            <button type="button" v-on:click="changeHandler" class="btn btn-default">修改</button>
            <button type="button" v-on:click="delateHandler" class="btn btn-default">删除</button>
          </div>
          <BtnGroup :products="products"></BtnGroup>
        </div>
        <br>
        <br>
        <table class="table table-bordered table-striped table-hover">
          <tr>
            <td><input type="checkbox" v-on:click="selectAll" name="selectAllBtn" v-model="selectAllState"/></td>
            <th>ID</th>
            <th>商品名称</th>
            <th>商品价格</th>
            <th>商品数量</th>
            <th>商品总价</th>
          </tr>
          <tr v-for="(product,index) in products">
            <td>
              <input type="checkbox" v-on:click="checkItem(product)" v-model="product.state" name="checkbox" />
            </td>
            <td>{{index+1}}</td>
            <td>{{product.name}}</td>
            <td>{{product.price}}</td>
            <td>
              <!--可以将两个按钮的方法合成一个,通过传参-->
              <!--<button @click="changeCount(prod, -1)">-</button>-->
              <button @click="cutCount(product)" class="btn btn-default btn-sm">-</button>
              <input type="number" v-model="product.count"/>
              <!--<button @click="changeCount(prod, 1)">-</button>-->
              <button @click="addCount(product)" class="btn btn-default btn-sm">+</button>
            </td>
            <td>{{product.price * product.count}}</td>
          </tr>
          <tr>
            <!--text-right排版文本右对齐-->
            <td colspan="5" class="text-right">总价:</td>
            <!--text-primary辅助类文本-->
            <td class="text-primary">{{totalMoney}}</td>
          </tr>
        </table>
      </div>
    </template>
    
    <script>
      /* eslint-disable no-new */
      import 'bootstrap/dist/css/bootstrap.min.css'
      import BtnGroup from './components/BtnGroup'
      export default{
        name: 'App',
        components: {BtnGroup},
        data:function(){
          return{
            products: [
              {
                name: '小米6S',
                price: 3999,
                count: 1,
                state:false
              },
              {
                name: '锤子2',
                price: 4999,
                count: 1,
                state:false
              },
              {
                name: '华为P20',
                price: 3599,
                count: 1,
                state:false
              },
              {
                name: 'OPPO R15',
                price: 2999,
                count: 1,
                state:false
              },
              {
                name: 'OPPO R11',
                price: 1999,
                count: 1,
                state:false
              },
            ],
            selectAllState:false
            /*
              注意:这里修正下,页面里的死数据,操作类的直接写好即可,不用遍历数据获取。
              只有页面中的展示信息即动态设置
             */
            /*
            buttons:[
              {title:'添加',class:'btn-primary',handler:function(){alert('点击添加按钮')}},
              {title:'修改',class:'btn-default',handler:function(){alert('点击修改按钮')}},
              {title:'删除',class:'btn-default',handler:function(){
                for(let i =0;i<app.data().products.length;i++){
    //              console.log(app.data().products[i].state)
                  if(app.data().products[i].state){
                    app.data().products.splice(i,1);
                    i--;
                  }
                };
                全选按钮状态清空
                document.querySelectorAll('input[name="selectAllBtn"]')[0].checked = false;
              }}
            ]
      */
          }
        },
        methods:{
          // 用户点击加减数量时调用
          cutCount:function(product){
            if(product.count>0){
              product.count--
            }else{
              alert('商品数量不能小于0')
            }
          },
          addCount:function(product){
            product.count++
          },
          checkItem:function(product){
            product.state = !product.state;
          },
          selectAll:function() {
            var checkObj = document.querySelectorAll('input[name="checkbox"]'); // 获取所有checkbox项
            if (event.target.checked) {
              // 点击全选事件
              for (var i = 0; i < checkObj.length; i++) {
                checkObj[i].checked = true;//选中样式
                this.products[i].state = true;//动态改变值,供删除用
              }
            } else {
              for (var i = 0; i < checkObj.length; i++) {
                checkObj[i].checked = false;
                this.products[i].state = false;
              }
            }
          },
          /*添加 */
          addHandler:function(){
            alert("点击添加按钮")
          },
          /* 修改 */
          changeHandler:function(){
            alert("点击修改按钮")
          },
          /* 删除 */
          delateHandler:function(){
            for(let i=0;i<this.products.length;i++){
              if(this.products[i].state){
                this.products.splice(i,1);
                i--;
              }
            }
             /* 注意:vue里尽量避免DOM操作。所有的操作都是数据驱动 */
            this.selectAllState = false;//还原全选按钮状态
          }
    
        },
        computed:{
          totalMoney:function(){
            var price = 0;
            for(var i = 0; i < this.products.length; ++i) {
              price += parseFloat(this.products[i].price * this.products[i].count);
            }
            return price;
          }
        }
    
      }
    //  module.exports = App;
    //  export default app;
    
    </script>
    
    <style>
      #app {
        font-family: 'Avenir', Helvetica, Arial, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        text-align: center;
        color: #2c3e50;
        margin-top: 60px;
      }
    </style>
  • 相关阅读:
    帧率、码流与分辩率之间关系
    谈谈RGB、YUY2、YUYV、YVYU、UYVY、AYUV
    YUV422 to YUV420sp color invert
    mysql——数据库备份——使用mysqldump命令备份所有数据库
    mysql——表的导出——用mysqldump命令导出 文本文件
    mysql——数据还原——使用mysql命令还原
    mysql——表的导出——用mysqldump命令导出 xml文件
    mysql——表的导出——用select……into outfile导出 xls文件和文本文件
    mysql——表的导出——用mysql命令导出 文本文件 和 xls文件
    和菜鸟一起学linux之wifi学习记录基础知识
  • 原文地址:https://www.cnblogs.com/fightjianxian/p/10634932.html
Copyright © 2011-2022 走看看