wepy 项目开发说明
功能列表
1 配置 window(外观)和 tabBar(底部 tab 栏)
2 首页页面结构和样式
3 首页获取接口数据渲染页面
发起请求:wepy.request({})
开启:不校验合法域名
4 开启 Promise/async 支持 和 封装 fetch
5 返回顶部
5.1 页面滚动到一定距离后才展示返回顶部按钮
5.2 点击返回顶部,实现页面回到顶部( wx.pageScrollTo(OBJECT) )
如何开始一个新功能
1 在 app.wpy 的 pages 中配置新页面路径
2 在 pages 目录中新建页面文件(文件名.wpy)
3 在 页面 中添加 template/style/script 三项内容
创建 wepy 文件报错说明
如果新建页面后小程序中报错,按以下方式处理:
1 终止 wepy build --watch 终端命令
2 关闭 微信开发者工具
3 删除 dist 文件夹
4 重新运行 wepy build --watch 命令
5 重新打开 微信开发者工具
说明:wepy 命令行工具自身的问题,会导致这个错误
小程序合法域名的说明
为了安全性的考虑,小程序中能够访问的接口域名需要在小程序管理后台配置后,才能正常访问
可以在 微信公众平台|小程序 中的 设置 -> 开发设置 -> 服务器域名 添加合法域名
在开发期间,可以绕过这个配置项,只需要在 微信开发者工具 中勾选 不校验合法域名,那么,小程序就可以请求任何域名的接口数据了
等到小程序真正上线的时候,就必须配置合法域名,否则,小程序无法正常获取数据以及上线
wepy 中数据操作的说明
读取数据
直接使用 this.swiperList 就可以访问了
设置数据
同步:this.swiperList = []
异步:
1 this.swiperList = []
2 this.$apply()
开启 Promise 和 async
注意:开启 Promise 支持后,原来 回调函数 的方式就不再支持了!
开启步骤如下:
1 安装:npm i -S wepy-async-function
2 修改 app.wpy,如下:
// 2.1 导入async包
import 'wepy-async-function'
export default class extends wepy.app {
constructor() {
super()
// 2.2 让wepy中的API变为Promise的使用方式
this.use('promisify')
}
}
3 重启编译:wepy build --no-cache
封装 fetch 的说明
为什么要封装 fetch?
1 因为 wepy 提供的 request 使用繁琐
如何封装?
1 先开启 wepy 的 Promise/async 支持
2 封装 fetch,代替 wepy.request
封装的具体操作:
1 处理 公共路径,以后每次请求的时候,只需要提供当前接口地址即可(BASEURL)
2 封装获取 data。封装前需要 res.data.data 才能获取到,封装后,只需要 res.data 就可以了
字体图标库
使用步骤:
1 下载字体图标样式文件
2 将其拷贝到项目的 assets 目录中,并且修改文件后缀名为:.wxss
3 修改 样式文件 中的 px 为 rpx
4 在 app.wpy 中通过 @impot '路径'; 来导入字体图标文件
5 在需要使用字体图标的位置,添加类名:class="iconfont icon-xiao"
小程序中的页面跳转
1 通过组件 navigator 来实现小程序中页面的跳转
2 要跳转到的页面一定要有,否则,就会报错:页面找不到
3 如果要跳转的页面是 tabBar 中的页面,需要设置 open-type="switchTab"
默认 open-type 为:navigate
两种 open-type
1 open-type="navigate"
1.1 默认值
1.2 用于普通页面跳转
1.3 跳转后,可以返回上一个页面
2 open-type="switchTab"
2.1 用于跳转到 tabBar 页面
2.2 跳转后,不能返回上一个页面
默认跳转
跳转到tabBar页面
导航传递参数
导航的时候,可以直接在 url 后面指定参数:
跳转并传递参数
在页面中,通过 onLoad 这个声明周期函数的参数 query 可以获取到传递的参数
// goods_detail.wepy 页面:
// 获取传递给该页面的参数
onLoad(query) {
console.log(query.goods_id)
}
微信开发者工具中的编译模式
说明:默认情况下,小程序每次打开的都是首页,这样就导致调试其他页面,需要点击多次,才能进入其他页面,很繁琐
解决方式:在 微信开发者工具 中,添加编译模式(比如:商品详情编译模式)
添加并切换到该编译模式后,每次启动都会从该模式制定的页面启动
wepy 中的事件绑定
1 在模板中通过 @tap 方式来给小程序的组件绑定事件
说明:绑定事件的方式,模拟 Vue 中事件绑定方式
2 页面中的事件处理程序都要放在 methods 实例属性中
3 如果需要传递参数,应该使用 {{ 参数 }} 来处理参数,否则,就会被当作字符串来处理了
点我
点我
export default class Index extends wepy.page {
methods = {
handleClick() {
// 事件处理程序
}
}
}
图片预览
wx.previewImage({ current: '', urls: [] })
商品详情 - 图片详情功能
说明:接口返回的图文详情数据是 HTML 结构的字符串,但是,小程序中是不支持 HTML 结构的。因此,需要将 HTML 结构,转化为 wxml 才能在小程序中展示出来
问题:如何将 HTML 转化为 wxml?
解决:使用第三方插件 wxParse
解析 HTML
说明:将 HTML 解析为 wxml
使用场景:服务器端返回的商品详情是 HTML 字符串,需要转化为 wxml 才能展示
使用步骤
1 下载 wxParse,git clone https://github.com/icindy/wxParse.git
2 将下载的文件中的 wxParse 目录,拷贝到 src/vendor 文件夹中
3 在 goods_detail.wpy 中导入 wxParse.js 文件
// 导入 wxParse 来解析HTML -> wxml
import WxParse from '../vendor/wxParse/wxParse'
4 在 goods_detail.wpy 中导入 wxParse.wxss 文件
// 导入 wxparse 的样式
@import '../vendor/wxParse/wxParse.wxss';
5 在 goods_detail.wpy 的 onLoad 钩子函数中调用一下代码
// 表示要转化的HTML结构
var article = '
我是HTML代码 '
var that = this
WxParse.wxParse('article', 'html', article, that, 5)
6 在需要展示 HTML 结构的位置引入模版
微信和小程序的关系
1 小程序是微信提供的一个功能,要打开小程序必须打开微信才可以
2 微信开发接口:都是需要用户授权给小程序,小程序才能够使用这些开发能力
加入购物车
1 从本地存储中获取到购物车中的数据
2 判断购物车中是否包含当前商品
3 如果购物车中已经有该商品,就让商品数量加 1
4 如果购物车中没有该商品,就直接添加到购物车中
5 将修改后的数据,保存到本地存储中
// 获取数据
wepy.getStorageSync('key')
// 设置数据
wepy.setStorageSync('key', value)
导航菜单点击态
1 navigator 导航组件,点击的时候默认会提供点击态效果(用户点击回馈)
2 如果不想要点击态,可以通过:hover-class="none"去掉点击态效果
3 也可以通过自定义类的方式,来修改默认的点击态效果:
.navigator-hover {
background-color: rgba(255, 0, 0, 0.8);
opacity: 0.7;
}
导入样式注意点
@import 相对路径;
注意:文件路径为 相对路径,不要使用绝对路径,否则会出现 Bug
Git 使用
刚进入公司,一般都是先通过 git 将项目 clone 到本地:git clone
实现一些功能后,需要将本地写完的代码,提交到git服务器中:git push 仓库地址
每天去公司开发前,都会使用 git pull 仓库地址 来获取下最新的代码
# 克隆仓库
git clone https://gitee.com/zqran/wepy-shop-22.git
# 推送
git push https://gitee.com/zqran/wepy-shop-22.git master
# 简化推送地址
git remote add wepy-shop https://gitee.com/zqran/wepy-shop-22.git
git push -u wepy-shop master
# 第一次执行上面两条命令,以后只需要输入以下命令即可
git push wepy-shop
# 拉取
git pull https://gitee.com/zqran/wepy-shop-22.git master
git pull wepy-shop master
购物车功能
商品总数量和总价格
说明:因为商品的数量改变会导致 商品总数量 和 总价格 改变,所以,商品总数量和总价格应该使用 计算属性 来总计
注意:只要有数据发生改变,那么计算属性就会被重新计算,不管整个数据是否与计算属性有关(与 Vue 不同)
商品选中状态
1 点击商品,实现选中状态的切换
2 全选按钮的选中状态处理
2.1 当所有商品都被选中了,全选按钮就应该选中
2.2 只要有一个商品没有选中,全选按钮就不应该被选中
2.3 因为切换单个商品的选中状态,会影响到全选按钮的选中状态,因此,应该使用计算属性来控制全选按钮的选中状态
3 (有点绕)点击全选按钮,切换全选按钮的选中状态
3.1 获取到当前全选按钮的选中状态(直接取计算属性值即可 this.selectAll)
3.2 改变全选按钮的选中状态以及每个商品的选中状态,但是分析后发现:只需要修改每个商品的选中状态即可
1 全选按钮的选中状态是由计算属性来控制
2 当修改了商品状态后,计算属性就会被自动重新计算一次,也就能够得到最新的商品选中状态了
3 所以,就不要再手动改变 全选按钮 的选中状态,而只需要修改每个商品的选中状态
商品数量
1 加号/减号按钮控制商品数量
2 减号减少商品的时候,临界值的判断(小于 1 ,则提示是否删除商品)
3 在文本框中直接输入修改商品数量(注意:只能输入数值)
直接修改文本框中的商品数量:
1 获取到用户输入的内容
2 判断用户输入的内容是不是正整数(使用正则判断)
3 如果是合法值,直接使用用户输入的内容来修改该商品的数量
4 如果不是合法值,直接返回该商品的数量
在小程序中,input输入事件如果使用return返回一个值,那么文本框的value就会变为这个return的值
保存购物车数据
方式一:使用 watch 监视数据的变化,当数据发生改变,就将购物车数据保存到本地存储中
方式二:使用 onHide 生命周期钩子函数,在离开购物车页面的时候,会触发这个钩子函数。可以在这个钩子函数中实现数据的保存
结算
1 控制结算按钮的样式
说明:如果购物车中有商品被选中了,就让结算按钮可用;如果没有任何一个商品选中,就让结算按钮禁用(禁用:添加 buy-disabled 类)
2 点击结算按钮根据是否有选中商品,来决定是否跳转到结算页面
2.1 如果有选中商品,就跳转到结算页面
2.2 如果没有选中商品,就提示用请勾选商品
微信授权登录和传统登录的对比说明
传统登录
使用 用户名 和 密码 来进行登录的
1 用户名 是唯一的,不同用户有不同的用户名
2 用户都有自己的 userId,并且不用用户的 userId 也是不相同的
3 用户名 和 userId 是一一对应的关系
4 用户名是为了用户方便记忆提供个用户的,userId 是程序区分不同用户时使用的
5 用户登录成功后,服务器会返回一个登录状态标识,比如:token
微信授权登录
说明:不管是什么登录方式,最终要达到的目的是相同的!!!
也就是说:
1 微信授权登录最终也要提供一个用来区分用户身份的唯一标识 openid(类似于 userId)
2 登录成功后,也应该返回一个登录状态标识(类似于 token)
所以,要实现微信授权登录,就要想办法获取到 用户身份的唯一标识 以及 登录状态
微信授权登录提供的用户身份唯一标识:opendId
对于登录状态来说,实际上与 传统登录 处理方式相同!
品优购服务器登录接口的说明
接口需要的数据如下:
code 用户登录凭证
encryptedData 完整用户信息密文
iv 加密算法的初始向量
rawData 用户信息原始数据字符串
signature 使用 sha1得到字符串
code 是用来做微信登录的
其他数据的作用:用于服务器端获取当前微信用户的 昵称、头像 等数据
订单
登录后下订单
调用登录接口,并且传递登录接口需要的参数
参数:
1 获取 code -> wx.login()
2 获取 encryptedData 等其他 用户数据
正确获取 encryptedData 等用户数据的正确方式:
说明:第一次会弹出 用户授权窗口;以后的每次,不会再弹出授权窗口,并且可以直接获取到用户数据
点击登录后下单
...
methods = {
wxLogin(e) {
// 获取用户信息数据
console.log(e.detail)
}
}
注意:获取用户数据时不能直接调用 wx.getUserInfo() 方法!!!
调用 wx.getUserInfo() 的问题说明:
直接调用 wx.getUserInfo() 方法来
获取用户信息(encryptedData 等数据)会出现左侧(警告)的提示。
这个提示说明这种获取用户信息的方式已经过时了,将来这种方式会被弃用,需要修改为全新的使用方法!!!
解决方式:
不再直接调用 getUserInfo() 方法来获取用户信息数据,而应该使用官方推荐的最新方式(参考小程序的文档)
https://developers.weixin.qq.com/miniprogram/dev/api/open.html#wxgetuserinfoobject
调用登录接口报错的说明
说明:这个错误只在开发小程序期间会有,小程序上线后就不会再出现这个问题了
错误信息:Error: invalid code, hints: [ req_id: cm32804974123 ]
为什么会出现 code 错误???
原因是:小程序项目中配置的 appid 和 服务器中配置的 appid/appsecret 不一致
解决方式:本地搭建服务接口,保证 小程序项目使用的 appid 和 本地接口服务中的 appid 一致即可
订单支付的流程总结
1 判断用户有没有指定收货地址
1.1 如果用户指定了收货地址,直接继续下一步
1.2 如果用户没有指定收货地址,就提示用户填写收货地址
2 创建订单
2.1 组装创建订单需要的数据
2.2 发起请求
2.3 服务器根据数据创建订单,并且返回结果( 订单编号 )
3 支付订单 - 预支付
目的:为了获取微信支付需要的数据
3.1 拿到 订单编号 传递给预支付接口
3.2 发起请求
3.2 服务器根据数据进行预支付,并且返回结果( wxorder 微信支付需要的数据 )
4 支付订单 - 发起微信支付
4.1 拿到 微信支付需要的数据
4.2 调用 wx.requestPayment(wxorder) 开发接口,发起微信支付
5.3 微信服务器返回支付的结果
5 查询支付结果
目的:上一步微信支付成功表示 微信服务器 已经收到用户支付的钱,但是,我们自己的服务器还不知道到底有没有支付成功,所以,需要再查询一次,查看自己的服务器中是否真正的支付成功
5.1 拿到上面的订单编号
5.2 发起请求
5.3 拿到服务器返回的数据,就知道 服务器 中是否确定支付成功了
6 支付成功,跳转到订单页面;支付是白,就提示用户重新支付
微信支付
说明:小程序开通微信支付功能后,才能使用微信支付的功能
配置拦截器
在 app.wpy 中,添加以下代码:
export default class extends wepy.app {
constructor() {
super()
// ... 省略其他代码
// 拦截request请求
// 配置拦截器后,将来所有通过 wx.request 发送的请求,都会
// 先经过拦截器,然后,才会真正的发送请求
// 因此,可以在 拦截器 中,给 请求头 添加 token
this.intercept('request', {
config(p) {
// 将 token 添加到请求头中
p.header.Authorization = wepy.getStorageSync('token')
// 必须返回OBJECT参数对象,否则无法发送请求到服务端
return p
}
})
}
// ... 省略其他代码
}
CSS 文字溢出省略
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
wepy 中 methods 配置的说明
注意:1 methods中的方法只能用在 wxml 中给组件绑定事件
所以,在 methods 中不能直接通过 this.方法名 来调用 methods 中的其他方法!!!
注意:2 如果要封装一个自定义方法,不能放在 methods 中,而应该与 methods 同级
methods = {
fn () {
// 调用自定义方法 foo
this.foo()
},
// 错误演示!!!
// foo() {}
}
// 自定义方法!!!
foo() { }
onLoad() {
this.foo()
}
我的 - 个人中心
问题:从哪获取当前用户的头像和昵称???
通过微信开发接口 getUserInfo 提供的
登录/注册
weui 的使用
WeUI 是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页和微信小程序量身设计,令用户的使用感知更加统一。
我们使用的是:WeUI for 小程序
weui 使用步骤
1 在 weui-wxss/dist/example 目录中找到要使用的功能
比如:weui-wxss/dist/example/searchbar
2 将 searchbar 目录中的 js/wxml/wxss 拷贝到项目中
3 在 app.wpy 中导入 weui.wxss 样式
4 将默认的效果,修改为适合我们自己项目的效果
wepy 中的组件使用
注意:1 组件继承自 wepy.component 页面继承自 wepy.page
注意:2 组件中没有 config 以及 一些钩子函数(比如:onPageScroll,onShow) 等配置,除此之外,其他的配置与页面相同
创建组件:
搜索框组件
import wepy from 'wepy'
// 注意:组件继承自 wepy.component
export default class Com extends wepy.component {}
使用组件:
// JS代码逻辑
import wepy from 'wepy'
// 1 导入组件
import SearchBar from '../components/SearchBar'
// 页面
export default class Search extends wepy.page {
// ... 省略其他配置
// 2 注册组件:
components = {
SearchBar
}
}
wepy 中的组件通讯
父 -> 子:props
export default class SearchBar extends wepy.component {
// ... 省略其他代码
// 组件接收传递过来的数据
props = {
searchTxt: {
// 类型:
type: String,
// 默认值
default: ''
}
}
}
子 -> 父:twoWay
props = {
parentAddress: {
// 子组件修改 parentAddress 这个props的时候,父组件会自动接收到修改后的数据
twoWay: true,
default: {}
}
}
搜索列表页面 - 触底加载更多数据
1 触底加载下一页的数据
1.1 先封装一个加载数据的方法
1.2 每次调用该方法,都让页码加 1,也就是加载下一页的数据
2 触底加载下一页的数据,应该判断是否还有更多数据
2.1 如果还有更多数据,就加载
2.2 如果没有更多数据,就提示用户:没有数据了
3 添加加载数据的提示效果
加载提示效果
1 数据加载中的提示效果
直接根据 isLoading 就可以控制
isLoading 表示:数据加载中
2 没有更多数据的提示效果
描述:当页面触底加载分页数据到达最后一页的时候,就展示没有更多数的提示
根据 !hasMore && total !== 0 就可以控制
3 查询不到数据的提示效果
描述:调用接口查询数据,但是,没有结果,就展示查询不到数据的提示
根据 !isLoading && list.length <= 0 就可以控制
封装 收货地址 组件
1 在 components 目录中创建 Address 组件
2 因为 收货地址组件 在不同页面中,结构不同,因此,我们使用 slot 的方式来指定组件结构
具体的结构作为子节点
3 将原来页面中绑定的获取收货地址事件和数据 移动到 Address 组件中
4 将子组件中的数据传递给父组件,由父组件来渲染数据
通过 twoWay: true 来将组件接收到的数据同步到父组件中
props = {
parentAddress: {
// 子组件修改 parentAddress 这个props的时候,会自动将父组件中对应的数据也修改掉
twoWay: true,
default: {}
}
}