选号组件

选号页面示例代码

<template>
    <div>
      <!--标题栏-->
      <title-bar  :needBack="needBack" title="博彩选号"></title-bar>

      <!--信息声明-->
      <lottery-info></lottery-info>

      <div style="color:darkgray">请选择6个红球,1个蓝球</div>

      <!--红球展示区域-->
      <red-ball-picker :data="randomRed" @onRedSelected="handleRedSelected"></red-ball-picker>
      <!--蓝球展示区域-->
      <blue-ball-picker :data="randomBlue" @onBlueSelected="handleBlueSelected"></blue-ball-picker>

      <button type="button" class="btn btn-default pull-right clearfix" @click="addOne()">添加</button>
      <div class="clearfix"></div>

      <!--机选按钮-->
      <div class="rdm-div">
        <button type="button" class="btn btn-default pull-right"  @click="addRandom()">机选</button>
        <select class="form-control select" v-model="num">
          <option>1</option>
          <option>2</option>
          <option>3</option>
          <option>4</option>
          <option>5</option>
        </select>
      </div>
      <!--5.底部菜单栏-->
      <div class="menu">
        <div class="menu-item" @click="goToCart">
          <span class="glyphicon glyphicon-shopping-cart"></span>
          <span class="badge" >{{cartSize}}</span>
          <p>购物车</p>
        </div>
        <div class="menu-item" @click="goToCart">
          <span class="glyphicon glyphicon-save"></span>
          <p>立即投注</p>
        </div>
      </div>
    </div>
</template>

<script>
    import TitleBar from '@/pages/common/TitleBar'
    import RedBallPicker from '@/pages/shopping/components/RedBallPicker'
    import BallUtils from '@/utils/BallUtils'
    import BlueBallPicker from "./components/BlueBallPicker";
    import LotteryInfo from "./components/LotteryInfo";
    import {mapActions,mapGetters} from 'vuex'

    export default {
        name: "select-page",
        components:{
          BlueBallPicker,
          TitleBar,
          RedBallPicker,
          LotteryInfo
        },
        data (){
          return{
            needBack:true,
            redBalls:[],
            blueBall:null,
            randomRed:null,
            randomBlue:null,
            num:1
          }
        },
        computed:{
          ...mapGetters(['cartSize']),
        },
        methods:{
          ...mapActions(['addToCart']),
          handleRedSelected(balls){
            this.redBalls = balls;
          },
          handleBlueSelected(ball){
            this.blueBall = ball;
          },
          addOne(){
            //先判断红球=0,蓝球=0,一个没有选话就随机产生一组
            if(this.redBalls!=null && this.redBalls.length==0 && this.blueBall == null){
              //随机产生一注彩票
              this.randomOne();
            }else if(this.redBalls!=null && this.redBalls.length==6 && this.blueBall != null){
              //判断选择的红球的数量是否=6,蓝球的数量=1,添加到购物车
              this.addToCart({redBalls:this.redBalls,blue:this.blueBall,count:1})
            }else{
              //否则条件不成立,提示红球6个蓝球1个
              alert("红球的数量须为6个,蓝球的数量为1个");
            }
          },
          randomOne(){
            this.randomRed = BallUtils.randomRed()
            this.randomBlue = BallUtils.randomBlue()
          },

          addRandom(){
            //根据用户机选的数量,随机产生
            let self = this
            for(let i=0; i < this.num; i++){
              self.randomOne();
              //将每次随机产生的号码,添加到购物车中
              self.addToCart({redBalls:self.randomRed,blue:self.randomBlue,count:1})
            }
          },
          goToCart(){
            this.$router.push('/cart')
          }
        }
    }
</script>

<style scoped>
  .select{
    float:right;
    width:90px;
  }

  .badge {
    background-color: red;
    position: absolute;
    top: -10px
  }

  .menu-item{
    width: 50%;
  }

  .rdm-div{
    margin-top: 15px;
  }
</style>

红球选号区域

我们首先来解决一下页面上球的显示问题,红球总共33个,如果我们直接写死的话,重复代码会很多,我们考虑来初始化这33个红球,示例代码如下

这里我们选用created这个生命周期钩子
created(){
          //初始化页面中的球数据
          for(let i = 1; i<=33; i++){
            let red = i;
            if(i < 10){
              red ="0"+i;
            }
            //每一个被初始化出来的红球都是没有被选中的状态
            this.balls.push({number:red.toString(),selected:false});
          }
 }
某个红球被选中
  1. 先判断当前球是否已经被选中
    1. 若被选中,则取消选中状态
      1. 将当前红球,从所有已选中的球中删除掉
    2. 若未被选中,则先判断当前选中的红球是否小于6个
      1. 若小于6个
        1. 修改当前求的状态
        2. 将当前球保存到所有选中的球中
      2. 若已经等于6个红球了
        1. 提示用户最多只能选择6个红球
  2. 通知父组件,红球选中的数据发生了改变

注意:我们这里只通知父组件选中球的信息,如["01","03","05","08","09","32"]

	handleRedClick(ball){
             //1.先判断当前球是否已经被选中
             if(ball.selected){
               //如果当前球已经被选中,则取消选中
               ball.selected = false;
               //将当前的球从被选中的数组中删除掉
               let index = this.selectedRedBalls.indexOf(ball.number);
               //删除元素
               this.selectedRedBalls.splice(index,1);
             }else{
               //判断当前选中的球是否小于6个
               if(this.selectedRedBalls.length < 6){
                 //选中当前球
                 ball.selected = true;
                 this.selectedRedBalls.push(ball.number);
               }else{
                 alert('红球最多只能选择6个')
               }
             }
            //通知父组件数据发生变化了
             this.$emit('onRedSelected',this.selectedRedBalls);
           }
<template>
  <div class="clearfix">
    <div v-for="ball in balls" :key="ball.number" class="col-xs-ball">
      <div class="ball-item ball-red" @click="handleRedClick(ball)" :class="{'ball-red-selected':ball.selected}">
        {{ball.number}}
      </div>
    </div>
  </div>
</template>

<script>
    export default {
        name: "red-ball-picker",
        props:{
          data:{
            type:Array,
            default:null
          }
        },
        data(){
          return {
            balls:[],
            selectedRedBalls:[]
          }
        },
        methods:{
           handleRedClick(ball){
             //1.先判断当前球是否已经被选中
             if(ball.selected){
               //如果当前球已经被选中,则取消选中
               ball.selected = false;
               //将当前的球从被选中的数组中删除掉
               let index = this.selectedRedBalls.indexOf(ball.number);
               //删除元素
               this.selectedRedBalls.splice(index,1);
             }else{
               //判断当前选中的球是否小于6个
               if(this.selectedRedBalls.length < 6){
                 //选中当前球
                 ball.selected = true;
                 this.selectedRedBalls.push(ball.number);
               }else{
                 alert('红球最多只能选择6个')
               }
             }
            //通知父组件数据发生变化了
             this.$emit('onRedSelected',this.selectedRedBalls);
           }
        },
        watch:{
          data(newVal,OldVal){
            //监听data数据的变化
            if(newVal != null && newVal.length == 6){
              //清空当前已经选择数组的状态
              this.selectedRedBalls = [];
              // 将新数据保存到当前选中的球数组中
              this.selectedRedBalls.push(...newVal);

              //修改页面上球的状态
              let self = this;
              this.balls.forEach(function(ball){
                let index = self.selectedRedBalls.indexOf(ball.number);

                ball.selected = index != -1;

              });

              //通知父组件数据发生变化了
              this.$emit('onRedSelected',self.selectedRedBalls);
            }
          }
        },
        created(){
          //初始化页面中的球数据
          for(let i = 1; i<=33; i++){
            let red = i;
            if(i < 10){
              red ="0"+i;
            }
            this.balls.push({number:red.toString(),selected:false});
          }
        }

    }
</script>

<style scoped>

</style>

蓝球选号区域

初始化16个蓝球

	created(){
          //初始化页面中的球数据
          for(let i = 1; i<=16; i++){
            let blue = i;
            if(i < 10){
              blue ="0"+i;
            }
            this.balls.push({number:blue.toString(),selected:false});
          }
        }
某个蓝球被选中
  1. 先取消前一次选中的蓝球的状态
  2. 修改当前选中蓝球的状态
<template>
  <div class="blue-containner">
    <div v-for="ball in balls" :key="ball.number" class="col-xs-ball">
      <div class="ball-item ball-blue" @click="handleBlueClick(ball)" :class="{'ball-blue-selected':ball.selected}">
        {{ball.number}}
      </div>
    </div>
  </div>
</template>

<script>
    export default {
        name: "blue-ball-picker",
        props:{
          data:{
            type:String,
            default:null
          }
        },
        data(){
          return {
            balls:[],
            selectedBall:null
          }
        },
        methods:{
           handleBlueClick(ball){
             //取消上一次选中的蓝球的选中状态
            if (this.selectedBall) {
              this.selectedBall.selected = false;
            }

            //将当前球的状态改为true
            ball.selected = true

            // 记录当前选中的球
            this.selectedBall = ball;
            //通知父组件数据发生变化了
            this.$emit('onBlueSelected', this.selectedBall.number);
           }
        },
        watch:{
          data(newVal,OldVal){
            //监听data数据的变化
            if(newVal != null){

              //修改页面上球的状态
              let self = this;
              this.balls.forEach(function(ball){
                if(ball.number === newVal){
                  ball.selected = true;
                  //清空上一次选中的状态
                  if(self.selectedBall != null){
                    self.selectedBall.selected = false;
                  }
                  self.selectedBall = ball;
                }
              });

              //通知父组件数据发生变化了
              this.$emit('onBlueSelected',this.selectedBall.number);
            }
          }
        },
        created(){
          //初始化页面中的球数据
          for(let i = 1; i<=16; i++){
            let blue = i;
            if(i < 10){
              blue ="0"+i;
            }
            this.balls.push({number:blue.toString(),selected:false});
          }
        }
    }
</script>

<style scoped>
  .red-containner{
    clear: both;
  }
</style>

VueX存储购物车

这里我们定义购物车里面的内容为如下格式:

{red:"01,03,05,08,09,32",blue:"13",count:2}

示例代码如下

//从浏览器内置的存储去获取数据
let jsonStr = localStorage.getItem("carts");
//将json字符串转成json数组
let defaultCarts = JSON.parse(jsonStr);

//定义保存数据的地方
const state={
  carts:defaultCarts // {red:'01,02,03,04,05,06',blue:"16",count:1}
}
//对外提供访问数据的方法
const getters={
  cartSize:(state)=>state.carts.length,
  getCarts:(state)=>state.carts,
  totalMoney:(state)=>{

    let totalCount = 0;
    state.carts.forEach((item)=>{
      totalCount+=item.count;
    });
    return totalCount*2;

  }
}

//对外提供获取数据的方法
const actions={
  // {red:'01,02,03,04,05,06',blue:"16",count:1}
  // 传递过来的数据是 {redBalls:this.redBalls,blueBall:this.blueBall,count:1};
  addToCart(context,data){
    console.log("actions中addToCart被调用");
    console.log("action提交数据给mutations去修改")
    let redBalls = data.redBalls;

    let red = "";
    redBalls.forEach((item)=>{
      red +=","+item;
    });
    red = red.substr(1);

    //console.log(red);

    let cartItem = {red:red,blue:data.blueBall,count:data.count};

    context.commit('mAddToCart',cartItem);
  },
  //清空购物车
  clearCarts(context){
    context.commit('mClearCarts');
  },

  //删除某一条记录
  deleteItem(context,cartItem){
    //action调用mutations去真的删除
    context.commit('mDeleteItem',cartItem);
  }

}
//跟踪数据变化的,vue需要的, 真正修改数据
const mutations = {
  mAddToCart(state,cartItem){

    console.log("mutations中修改数据:"+cartItem);
    state.carts.push(cartItem);

    //将内存中的数据保存到浏览器本地
    localStorage.setItem("carts",JSON.stringify(state.carts))
  },

  //真正清空数组的地方
  mClearCarts(state){
    state.carts=[];

    localStorage.clear();
  },
  mDeleteItem(state,cartItem){
    let index = state.carts.indexOf(cartItem);

    //删除记录
    state.carts.splice(index,1);

    localStorage.setItem("carts",JSON.stringify(state.carts))
  }
}

//导出文件的所有内容
export default {
  state,getters,actions,mutations
}

购物车页面

购物车组件

<template>
  <div>
    <!--需要返回按钮的标题栏-->
    <title-bar :needBack="true" title="购物车"></title-bar>
    <!--需要轮播图-->
    <swiper></swiper>
    <!--需要彩票信息-->
    <lottery-info></lottery-info>

    <!--三个按钮组-->
    <div class="row" style="margin-bottom: 10px;">
      <div class="col-xs-4">
        <button type="button" class="btn btn-default" @click="handleSelect">+手动选号</button>
      </div>
      <div class="col-xs-4">
        <button type="button" class="btn btn-default" @click="handleRandom">+机选一注</button>
      </div>
      <div class="col-xs-4">
        <button type="button" class="btn btn-default" @click="handleClear">清空列表</button>
      </div>
    </div>

    <!--展示购物项条目-->
    <div>
       <shopping-item v-for="item in carts" :key="item.red" :data="item" @onDeleteItem="deleteItem" ></shopping-item>
    </div>

    <!--底部的菜单栏-->
   <div style="height: 50px">
     <div class="menu" >
       <div class="menu-item" @click="submitOrder" >
         <p>立即付款 {{totalMoney}}元</p>
       </div>
     </div>
   </div>

  </div>
</template>

<script>
    import TitleBar from '@/pages/common/TitleBar';
    import Swiper from '@/pages/common/Swiper';
    import LotteryInfo from './components/LotteryInfo'
    import ShoppingItem from './components/ShoppingItem'
    import BallUtils from '@/utils/BallUtils'
    import {mapActions,mapGetters} from 'vuex'
   

    export default {
        name: "cart-page",
        components:{
          Swiper,
          TitleBar,
          LotteryInfo,
          ShoppingItem
        },
        methods:{
          ...mapActions({
             addToCart:"addToCart",
             clearCart:"clearCart",
             deleteOne:'deleteOne'
          }),
          handleSelect(){
            //跳转去选号页面
            this.$router.go(-1);
          },
          handleRandom(){
            let redBalls = BallUtils.randomRed();
            let blue = BallUtils.randomBlue();
            this.addToCart({redBalls:redBalls,blue:blue,count:1});
          },
          handleClear(){
            //this.$store.dispatch('clearCart')
            this.clearCart()
          },
          deleteItem(cart){
            this.deleteOne(cart);
          }
        },
        computed:{
          ...mapGetters({
            carts:"carts",
            totalMoney:"totalMoney"
          })
        }
    }
</script>

<style scoped>
  .menu{
    height: 60px;
  }
  .menu-item{
    width: 100%;
    text-align: center;
    height: 50px;
    line-height: 50px;
  }
</style>

购物项组件

<template>
  <div class="row shop-item" >
    <div class="col-xs-1" @click="handleDelete(data)" style="padding-left: 10px;padding-top: 18px;">
      <!--删除的图标-->
      <span v-if="showDelete" class="glyphicon glyphicon-remove-circle"></span>
    </div>
    <div class="col-xs-10" style="padding-right: 0px;padding-left: 5px" >
      <div>
        <div class="ball-item ball-red" v-for="red in data.red.split(',')" :key="red">{{red}}</div>

        <div class="ball-item ball-blue" >{{data.blue}}</div>
      </div>
      <div style="margin-top: 5px;">单式{{data.count}}注 {{data.count*2}}元</div>
    </div>
    <div class="col-xs-1" style="padding-left: 5px;padding-top: 18px;">
      <!--小箭头-->
      <span v-if="showRight" class="glyphicon glyphicon-chevron-right"></span>
    </div>
  </div>
</template>

<script>
    export default {
        name: "shopping-item",
        props:{
          showDelete:{
            type:Boolean,
            default:true
          },
          showRight:{
            type:Boolean,
            default:true
          },
          data:{
            type:Object
          }
        },
        methods:{
          handleDelete(){
            this.$emit('onDeleteItem',this.data)
          }
        }
    }
</script>

<style scoped>
  .shop-item{
    padding-top: 10px;
    padding-bottom: 10px;
    border: 1px solid #E5E5E5;
  }
</style>

生产环境打包

项目中我们编写的vue文件并不能直接丢给服务器。

vue-cli为我们提供了一键打包的功能,并自动为我们进行了资源压缩,合并,小图进行base64,css编译等很多功能,只需要执行以下命令即可:

npm run build

将打包出来的dist目录下的内容,丢给服务器人员即可。

回顾:
第一天: 基础语法
	v-model
	v-for
	v-if
	props
	$emit 对外发消息
	:class
	:属性名=js代码
	data:{}
	computed:{}
	watch:{}
	methods:{}
	mounted:{} 若有异步请求
	created:{} 同步处理 
	
	单文件组件:局部组件
第二天:
	网站首页 axios 发起异步请求
	    博彩详情页面: this.$router.push  组件之间的跳转
        			this.$router.go() 
     共享数据: Vuex
     	登录页面 
     	用户页面 
     	new Vuex.Store({
            module:{
                
            }
     	});
     	const state={}    存储数据
     	const getters={}  相当于是javabean中Get方法 获取数据方法
     	const actions={}  相当于是set方法, 对外提供修改数据的方法
     	const mutations={} 内部自己真正去修改数据的地方
 第三天:
 	选中球
 	机选球
 	添加记录去vuex
 	购物车去展示数据
 	
 	localStorage
     	
链接:https://pan.baidu.com/s/1DzCJJtGVYThF4YxwqqxDmw 密码:8uan     
链接:https://pan.baidu.com/s/1EBJjxH-OObV2r50tXg88DQ 密码:rj4n