支付功能
wx.request() 的封装
//统计/同时发送异步请求代码的次数
let ajaxTmes = 0;
export const request = (params) => {
ajaxTmes++;
//显示加载中效果
wx.showLoading({
title: "加载中",
mask: true,
});
//定义url的公共部分
const baseUrl = "https://api-hmugo-web.itheima.net/api/public/v1";
return new Promise((resolve, reject) => {
wx.request({
//解构,将请求参数按格式赋值 属性名:变量名(即值) (其中属性名和变量名相同)
...params,
url: baseUrl + params.url,
success: (result) => {
resolve(result.data.message);
},
fail: (err) => {
reject(err);
},
//无论成功或者失败都会回调
complete: () => {
ajaxTmes--;
if (ajaxTmes == 0) {
//关闭正在等待的图标
wx.hideLoading();
}
}
});
})
}
使用封装的需每个页面文件的js文件中引入
//引入用来发送请求的方法 一定要把路径补全
import { request } from "../../request/index.js";
图标库
阿里云淘宝矢量图标库
app.wxss(全局css配置)
- @import : 引入其他.wxss文件样式 使全部页面无需引入则可调用类名的样式
- *{}:小程序不支持通配符
- 主题颜色:通过变量来定义
--themeColor:#1296db;//定义 color:var(--themeColor);//引用
-
1.less中存在变量这个知识
2.原生的css和wxss也是支持变量
-
/* 引入其他wxss样式 使全部页面无需引入则可调用类名的样式 */
@import "./styles/iconfont.wxss";
/* 小程序不支持通配符 */
page,view,text,swiper,swiper-item,image,navigator{
padding:0;
margin:0;
box-sizing: border-box;
}
/* 主题颜色 通过变量来实现
1.less中存在变量这个知识
2.原生的css和wxss也是支持变量
*/
page{
/* 定义主题颜色 */
--themeColor:#1296db;
/*定义统一的字体大小 假设设计稿大小是375px
1px=2rpx
14px=28rpx */
font-size: 28rpx;
}
image{
width: 100%;
}
app.json(全局配置)
- pages 通过添加保存(微信小程序 系统自动生成对应的文件)
- tabBar 设置tab栏 即tab页面 ,其中 list 最少2个页面 最多5个页面
"tabBar": {
"color": "#999",
"selectedColor": "#229ddd",
"backgroundColor": "",
"position": "bottom",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "icons/仓库.png",
"selectedIconPath": "icons/仓库-change.png"
}},
json文件(非app.json)
- 可引入组件
- 可自定义导航顶部的配置
- 可设置页面的
{
"component": true,
"usingComponents": {}
}
组件(js文件)
自定义组件的js
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})
1.搜索栏组件(SearchInput)
js
<view class="search_input">
<navigator url="/pages/search/index" open-type="redirect" >搜索</navigator>
</view>
less
.search_input{
height: 90rpx;
padding: 10rpx;
background-color: var(--themeColor);
navigator{
display:flex;
justify-content: center;
align-items: center;
background-color:white;
height: 100%;
border-radius: 15rpx;
color: #666;
}
}
2.标签栏组件(Tabs)
js
// components/Tabs/Tabs.js
Component({
/**
* 组件的属性列表
*/
properties: {
tabs:{
type:Array,
value:[]
}
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
//点击事件
handleItemTap(e){
//1.获取点击的索引
const {index}=e.currentTarget.dataset;
//2.触发父组件的事件自定义
this.triggerEvent("tabsItemChange",{index});
}
}
})
less
/* components/Tabs/Tabs.wxss */
.tabs {
.tabs_title {
display: flex;
width: 100%;
.title_item {
display : flex;
justify-content: center;
align-items : center;
flex : 1;
padding : 15rpx 0;
}
.active {
color : var(--themeColor);
border-bottom: 5rpx solid currentColor;
}
}
.tabs_content {}
}
wxml
<view class="tabs">
<view class="tabs_title">
<view
wx:for="{{tabs}}"
wx:key="id"
class="title_item {{item.isActive?'active':''}}"
bindtap="handleItemTap"
data-index="{{index}}"
>
{{item.value}}
</view>
</view>
<view class="tabs_content">
<slot ></slot>
</view>
</view>
1.view
2.navigator
- url
- open-type
3.swiper
- autoplay
- indicator-dots
- circular
4.swiper-item
5.image
- mode
- src
6.block
7.button
- open-type
- bindgetuserinfo
- type
8.scroll-view
- scroll-y
- scroll-x
9.checkbox-group
- bindchange
10.checkbox
- checked
功能模块总结
轮播图总结
- swiper标签存在默认的宽度和高度*
100%*150px
- .imgae标签也存在默认的宽度和高度*
320px*240px
- 设计图片和轮播图*
1.先看一下原图的宽高750*340
2.让图片的宽高自适应宽度等于100%
3.让swiper标签的高度变成和图片的高一样即可
- 图片标签*
model属性 渲染模式
widthFix 让图片的标签宽高和图片标签的内容
商品列表
/*
1用户上滑页面滚动条触底开始加载下一页数据
1找到滚动条触底事件微信小程序官方开发文档寻找
2判断还有没有下一页数据
1获取到总页数只有总条数
总页数=Math.ceil(总条数/页容量pagesize)
总页数=Math.ceil(23/18)=3
2获取到当前的页码 pagenum
3判断一下当前的页码是否大于等于总页数
表示没有下一页数据
3假如没有下一页数据弹出一个提示
4假如还有下一页数据来加载下一页数据
1当前的页码++
2重新发送请求
3数据请求回来 要对data中的数组进行拼接而不是全部替换!!!|I
2下拉刷新页面
1触发下拉刷新事件需要在页面的json文件中开启一个配置项
找到触发下拉刷新的事件
2重置数据数组
3重置页码设置为1
4重新发送请求
5数据请求回来需要手动的关闭等待效果
// pages/goods_list/index.js
import { request } from "../../request/index.js";
/*
1用户上滑页面滚动条触底开始加载下一页数据
1找到滚动条触底事件微信小程序官方开发文档寻找
2判断还有没有下一页数据
1获取到总页数只有总条数
总页数=Math.ceil(总条数/页容量pagesize)
总页数=Math.ceil(23/18)=3
2获取到当前的页码 pagenum
3判断一下当前的页码是否大于等于总页数
表示没有下一页数据
3假如没有下一页数据弹出一个提示
4假如还有下一页数据来加载下一页数据
1当前的页码++
2重新发送请求
3数据请求回来 要对data中的数组进行拼接而不是全部替换!!!|I
2下拉刷新页面
1触发下拉刷新事件需要在页面的json文件中开启一个配置项
找到触发下拉刷新的事件
2重置数据数组
3重置页码设置为1
4重新发送请求
5数据请求回来需要手动的关闭等待效果
*/
Page({
data: {
tabs: [
{
id: 0,
value: "综合",
isActive: true
},
{
id: 1,
value: "销量",
isActive: false
},
{
id: 2,
value: "价格",
isActive: false
}
],
goodsList: []
},
//接口要的数据
QueryParams: {
query: "",
cid: "",
pagenum: 1,
pagesize: 10
},
totalPages: 1,
onLoad: function (options) {
this.QueryParams.cid = options.cid||"";
this.QueryParams.query=options.query||"";
this.getGoodsList();
// wx.showLoading({
// title:'加载中',
// });
// setTimeout(function(){
// wx.hideLoading()
// },5000)
},
//获取商品列表数据
getGoodsList() {
request({ url: "/goods/search", data: this.QueryParams })
.then(result => {
console.log(result)
const total = result.total;
//计算总页数
this.totalPages = Math.ceil(total / this.QueryParams.pagesize);
this.setData({
//拼接了数组
goodsList:[...this.data.goodsList,...result.goods]
}
)
//关闭下拉刷新的窗口
wx.stopPullDownRefresh();
})
},
//标题点击事件 从子组件传递过来
handleTapsItemChange(e) {
//1.获取被点击的标题索引
const { index } = e.detail;
let { tabs } = this.data;
tabs.forEach((v, i) => i === index ? v.isActive = true : v.isActive = false);
this.setData({
tabs
})
},
//页面上滑 滚动条触底事件
onReachBottom() {
//判断有没有下一页数据
if (this.QueryParams.pagenum >= this.totalPages) {
//没有下一页数据
wx.showToast({
title: '没有下一页数据'
});
}else{
//还有下一页数据
this.QueryParams.pagenum++;
this.getGoodsList();
}
},
//下拉刷新
onPullDownRefresh(){
//1.重置数组
this.setData({
goodsList:[]
})
//2重置页码
this.QueryParams.pagenum=1;
//3发送请求
this.getGoodsList();
}
})
商品详情
/*
1发送请求获取数据
2点击轮播图预览大图
1给轮播图绑定点击事件I
2调用小程序的api previewImage
3点击加入购物车
1先绑定点击事件
2获取缓存中的购物车数据数组格式|
3先判断当前的商品是否已经存在于购物车
4已经存在修改商品数据执行购物车数量++重新把购物车数组填充回缓存中
5不存在于购物车的数组中直接给购物车数组添加一个新元素新元素带上购买数量属性num重新把购物车数组填充回缓存中
6弹出提示
*/
缓存模块
0.web中的本地存储和小程序中的本地存储的区别
1.写代码的方式不一样了
web:localStorage.setItem(“key”,“value”) localStorage.getItem(“key”)
小程序:wx.setStorageSync(“key”,“value”);wx.getStorageSync(“key”);
2.存的时候 有没有做类型转换
web:不管存入的是什么类型的数据,最终都会先调用以下toString(),把数据变成了字符串 再存入进去
小程序:不存在 类型转换的这个操作 存什么类型的数据进去,获取的时候就是什么类型
1.先判断一下本地存储中有没有旧的数据
{time:Date.now(),data:[…]}
2.没有旧数据 直接发送新请求
3.有旧的数据 同时 旧的数据也没有过期
就使用本地存储的旧数据
购物车模块
// pages/cart/index.js
/*
1获取用户的收货地址
1绑定点击事件
2调用小程序内置api获取用户的收货地址
3获取用户对小程序所授予获取地址的权限状态scope
1假设用户点击获取收货地址的提示框确定 authsetting scope.address
scope值true直接调用获取收货地址
2假设用户从来没有调用过收货地址的api
scope undefined直接调用获取收货地址
3假设用户点击获取收货地址的提示框取消
scope值false
1诱导用户自己打开授权设置页面(openSetting)当用户重新给与获取地址权限的时候
2获取收货地圳T
4把获取到的收货地址存入到本地存储中I
2页面加载完毕
0 onload onShow
1获取本地存储中的地址数据
2把数据设置给data中的一个变量
3 onShow
0 回到了商品详情页面第一次添加商品的时候手动添加了属性
1 num=1;
2 checked=true;
1获取缓存中的购物车数组
2把购物车数据填充到data中
4 全选的实现 数据的展示
1 onShow获取缓存中的购物车数组
2 根据购物车中的商品数据所有的商品都被选中checked=true全选就被选中
5总价格和总数量
1都需要商品被选中我们才拿它来计算
2获取购物车数组
3遍历
4判断商品是否被选中I
5总价格+=商品的单价*商品的数量
5总数量+=商品的数量
6把计算后的价格和数量设置回data中即可可
6商品的选中
1绑定change事件
2获取到被修改的商品对象
3商品对象的选中状态取反
4重新填充回data中和缓存中
5重新计算全选。总价格总数量。。。
7全选和反选
1全选复选框绑定事件 change
2获取data中的全选变量allchecked
3直接取反allchecked=la1lchecked
4遍历购物车数组让里面商品选中状态跟随a1lchecked 改变而改变
5把购物车数组和allchecked重新设置回data把购物车重新设置回缓存中
8商品数量的编辑
1"+"“-”按钮绑定同一个点击事件区分的关键自定义属性
1“+”"+1"
2"""-1"
2传递被点击的商品id goods_id
3获取data中的购物车数组来获取需要被修改的商品对象
4[当购物车的数量=1同时用户点击“”
弹窗提示(showModal)询问用户是否要删除
1确定直接执行删除
2取消什么都不做
4直接修改商品对象的数量num
5把cart数组重新设置回缓存中和data中 this.setCart
9点击结算
1判断有没有收货地址信息
2判断用户有没有选购商品
3经过以上的验证跳转到支付页面!
*/
js es6语法
Math.ceil
…this.data.goodsList
数组拼接
goodsList:[…this.data.goodsList,…result.goods]
forEach
字符串替换 replace 正则表达式
.map
.map(v**=>**({…v,create_time_cn:(new Date(v.create_time*1000).toLocaleString())}))