逆战班——停课不听学之小程序解析

1、全局配置

小程序根目录下的 app.json 文件用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。

以下是一个包含了部分常用配置选项的 app.json :——完整全局配置说明请参考:https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html

{
  "pages": [
    "pages/index/index",
    "pages/logs/index"
  ],
  "window": {
    "navigationBarTitleText": "Demo"
  },
  "tabBar": {
    "list": [{
      "pagePath": "pages/index/index",
      "text": "首页"
    }, {
      "pagePath": "pages/logs/index",
      "text": "日志"
    }]
  },
  "networkTimeout": {
    "request": 10000,
    "downloadFile": 10000
  },
  "debug": true,
  "navigateToMiniProgramAppIdList": [
    "wxe5f52902cf4de896"
  ]
}

2、页面配置

每一个小程序页面也可以使用同名 .json 文件来对本页面的窗口表现进行配置,页面中配置项会覆盖 app.json 的 window 中相同的配置项。

例如:——完整页面配置说明请参考:https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/page.html

{
  "navigationBarBackgroundColor": "#ffffff",
  "navigationBarTextStyle": "black",
  "navigationBarTitleText": "微信接口功能演示",
  "backgroundColor": "#eeeeee",
  "backgroundTextStyle": "light"
}

3、购物车流程

​ 购物车的需求:

​ 单选、全选和取消,而且会随着选中的商品计算出总价
​ 单个商品购买数量的增加和减少
​ 删除商品。当购物车为空时,页面会变为空购物车的布局

​ 首先是一个商品列表(carts),列表里的单品需要:商品图(image),商品名(title),单价(price),数量(num),是否选中(selected),商品id(id)然后全选,需要一个字段(selectAllStatus)表示是否全选了,总价(totalPrice),最后需要知道购物车是否为空(hasList)

代码实现

初始化

Page({
  data: {
    carts:[],        // 购物车列表
    hasList:false,     // 列表是否有数据
    totalPrice:0,      // 总价,初始为0
    selectAllStatus:true  // 全选状态,默认全选
  },
  onShow() {
    this.setData({
     hasList: true,    // 有数据了,设为true
     carts:[
      {id:1,title:'小米手机',image:'',num:4,price:0.01,selected:true},
      {id:2,title:'三星手机',image:'',num:1,price:0.03,selected:true}
     ]
    });
   },
})

布局wxml

<view class="cart-box">  
<!-- wx:for 渲染购物车列表 -->  
	<view wx:for="{{carts}}">      
	<!-- wx:if 是否选择显示不同图标 -->    
	<icon wx:if="{{item.selected}}" type="success" color="red" bindtap="selectList" data-index="{{index}}" />    
	<icon wx:else type="circle" bindtap="selectList" data-index="{{index}}"/>        
	<!-- 点击商品图片可跳转到商品详情 -->    
	<navigator url="../details/details?id={{item.id}}">      
		<image class="cart-thumb" src="{{item.image}}"></image>    
	</navigator>        
	<text>{{item.title}}</text>    
	<text>¥{{item.price}}</text>        
	<!-- 增加减少数量按钮 -->    
	<view>      
		<text bindtap="minusCount" data-index="{{index}}">-</text>      
		<text>{{item.num}}</text>      
		<text bindtap="addCount" data-index="{{index}}">+</text>    
	</view>        
	<!-- 删除按钮 -->    
	<text bindtap="deleteList" data-index="{{index}}"> × </text>  
	</view>
</view>
<!-- 底部操作栏 -->
<view>
  <!-- wx:if 是否全选显示不同图标 -->
  <icon wx:if="{{selectAllStatus}}" type="success_circle" color="#fff" bindtap="selectAll"/>
  <icon wx:else type="circle" color="#fff" bindtap="selectAll"/>
  <text>全选</text>
  <!-- 总价 -->
  <text>¥{{totalPrice}}</text>
</view>

计算总价

getTotalPrice() {
  let carts = this.data.carts; // 获取购物车列表
  let total = 0;
  for(let i = 0; i<carts.length; i++) { // 循环列表得到每个数据
    if(carts[i].selected) { // 判断选中才会计算价格
      total += carts[i].num * carts[i].price;   // 所有价格加起来
    }
  }
  this.setData({ // 最后赋值到data中渲染到页面
    carts: carts,
    totalPrice: total.toFixed(2)
  });
}

​ 单选事件

selectList(e) {
  const index = e.currentTarget.dataset.index;  // 获取data- 传进来的index
  let carts = this.data.carts;  // 获取购物车列表
  const selected = carts[index].selected; // 获取当前商品的选中状态
  carts[index].selected = !selected; // 改变状态
  this.setData({
    carts: carts
  });
  this.getTotalPrice();  // 重新获取总价
}

​ 全选事件

selectAll(e) {
  let selectAllStatus = this.data.selectAllStatus;  // 是否全选状态
  selectAllStatus = !selectAllStatus;
  let carts = this.data.carts;

  for (let i = 0; i < carts.length; i++) {
    carts[i].selected = selectAllStatus;// 改变所有商品状态
  }
  this.setData({
    selectAllStatus: selectAllStatus,
    carts: carts
  });
  this.getTotalPrice();// 重新获取总价
}

​ 增减数量

// 增加数量
addCount(e) {
  const index = e.currentTarget.dataset.index;
  let carts = this.data.carts;
  let num = carts[index].num;
  num = num + 1;
  carts[index].num = num;
  this.setData({
   carts: carts
  });
  this.getTotalPrice();
},
// 减少数量
minusCount(e) {
  const index = e.currentTarget.dataset.index;
  let carts = this.data.carts;
  let num = carts[index].num;
  if(num <= 1){
   return false;
  }
  num = num - 1;
  carts[index].num = num;
  this.setData({
   carts: carts
  });
  this.getTotalPrice();
}

​ 删除商品

deleteList(e) {
  const index = e.currentTarget.dataset.index;
  let carts = this.data.carts;
  carts.splice(index,1);  // 删除购物车列表里这个商品
  this.setData({
    carts: carts
  });
  if(!carts.length){// 如果购物车为空
    this.setData({
      hasList: false  // 修改标识为false,显示购物车为空页面
    });
  }else{ // 如果不为空
    this.getTotalPrice(); // 重新计算总价格
  }  
}
  

4、组件的使用

在写小程序的时候,有时候页面的内容过多,逻辑比较复杂,如果全部都写在一个页面的话,会比较繁杂,代码可读性比较差,也不易于后期代码维护,这时候可以把里面某部分功能抽出来,单独封装为一个组件,也就是通常说的自定义组件,自定义组件类似于页面,它有wxml 模版、wxss 样式和js文件,然后在页面中使用该自定义组件即可。

我的自定义组件代码结构是这样的:

myComponent文件就是我所创的自定义组件,myComponent.wxml文件代码为:

<view class="inner">
  <Text>I am learning 微信小程序</Text>
</view><view class="inner">

myComponent.js文件代码为:

const app = getApp()
Component({
  properties: {
    // 这里定义了innerText属性,属性值可以在组件使用时指定
    innerText: {
      type: String,
      // value: '',
    }
  },
  data: {
    // 这里是一些组件内部数据
    someData: {}
  },
  methods: {
    customMethod(){
      console.log('hello world! I am learning 微信小程序')
    }
  }
})


myComponent.wxss部分代码如下:

.inner{
  color:red
}

现在我要在pages/index文件中使用该自定义组件如下:

1、在myComponent.json文件中添加以下代码:

{
  "component": true
}

2、在需要调用自定义组件的文件中,如pages/index文件需要调用自定义组件,那么则需要在pages/index/index.json文件中添加如下代码:

{
  "usingComponents": {
    "myComponent": "../../components/myComponent/myComponent"   // 组件名以及组件所在路径
  }
}

3、然后就可以在myComponent.wxml文件中使用该自定义组件了,

index.wxml文件代码如下:

<view>
    <myComponent id="myComponent"></myComponent>
</view>

4、现在要调用自定义组件中的方法就可以这样做,为了方便,这里我使用的是点击按钮调用事件,因此index.wxml文件代码变为:

<view>
    <button bindtap="showComponent">组件调用</button>
    <myComponent id="myComponent"></myComponent>
</view>

5、myComponent.js文件部分代码为:

// pages/index/index.js
Page({
  /**
   \* 页面的初始数据
   */
  data: {

  },
  /**
   \* 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
    //  页面初次渲染完成后,使用选择器选择组件实例节点,返回匹配到组件实例对象  
    this.myComponent = this.selectComponent('#myComponent')
  },

  /**
   \* 生命周期函数--监听页面显示
   */
  onShow: function () {

  },

 23:02:14
/**
   \* 生命周期函数--监听页面隐藏
   */
  onHide: function () {
 
  },
 
  /**
   \* 生命周期函数--监听页面卸载
   */
  onUnload: function () {
 
  },
   showComponent: function () {
      let myComponent = this.myComponent
      myComponent.customMethod()  // 调用自定义组件中的方法
   }
})

  

版权声明:本文为zmh_1205原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。