微信小程序前期准备材料
部署线上接口环境,微信小程序要求
https
接口文档,有道/语雀在线文档编辑工具或者部署
doclevel
申请微信小程序并提供微信小程序
appid
(接口还会用到secret
)登录微信小程序后台管理配置服务器域名;把我们加到项目成员(开发者权限)
申请微信商户号(与微信小程序同主体),并和微信小程序关联。
相关API、资源
微信内小程序
- “小程序助手”(可以管理自己参与的项目)
- “小程序示例”
- “ColorUI组件库”
- “WeUI库”
基础
微信开发工具
app.json
中配置页面路由
普通编译改成“添加编译模式”,可以改变启动的页面和其他的扫码进入等等方式
“预览”:会在编译器左侧展示
“上传”:上传测试版or正式版,填写相应的版本号和备注信息
“测试”:微信会发一份测试报告过来
“详情”:不校验域名不要勾选上(否则可能在正式线上会有问题)
视图层与逻辑层关系
程序的每个页面都会维护一份数据源,所以在wxml
中用data-字段名称
除了需要在对应的(js
中)this.setData
或that.setData
中声明这个字段名称,最好还需要在data数据源中加上。
that.setData({ toastHidden: false })
//这里使用了that,这样就可以获取Page({})
对象。在wxml
中可以直接通过{{toastHidden}}
获取这个值
另外:
代码结构
没有操作dom
结点,通过数据去渲染,更像vue
、react
Page的生命周期配置:https://mp.weixin.qq.com/debug/wxadoc/dev/framework/app-service/page.html
app.js
:程序启动先访问它,全局配置(可以设置数据共享Storage
、全局数据)app.json
:pages
配置页面路由(在app.js
的pages
中添加,根目录下pages
代码会自动生成),windows
:写导航栏的样式(navigationBarTextStyle
提供了black
和white
两种)- pages中新建Page的时候会自动添加,但是删除却需要手动删除
app.json
里面的page配置 - windows中全局配置导航栏中间的文字:navigationBarTitleText
- windows中navigationBarBackgroundColor:导航栏的背景颜色
- tabbar中:底部切换页签(当设置position为top时,将不会显示icon)
- pages中新建Page的时候会自动添加,但是删除却需要手动删除
app.wxss
:全局的样式(@import "colorui/main.wxss";
导入别的样式)project.config.json
:我们写自定义编译等的配置都会在这里面
单位:rpx
rpx
单位是微信小程序中css
的尺寸单位,rpx
可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx
。如在 iPhone6(750x1334) 上,屏幕宽度为375px
,共有750个物理像素,则750rpx = 375px = 750物理像素
,1rpx = 0.5px = 1物理像素
。
设备 | rpx换算px (屏幕宽度/750) | px换算rpx (750/屏幕宽度) |
---|---|---|
iPhone5 | 1rpx = 0.42px | 1px = 2.34rpx |
iPhone6 | 1rpx = 0.5px | 1px = 2rpx |
iPhone6s | 1rpx = 0.552px | 1px = 1.81rpx |
微信小程序也支持rem
尺寸单位,rem
和rpx
的换算关系:rem: 规定屏幕宽度为20rem
;1rem = (750/20)rpx
注:开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。
建议:设计稿使用设备宽度750px
比较容易计算750px
的话1rpx=1px
,这样的话,设计图上量出来的尺寸是多少px
就是多少rpx
,至于在不同的设备上实际上要换算成多少个rem
就交给小程序自己换算
列表
wx:for="{{在index.js的data数据源中的数据对象}}"
在index.js
的data数据源中定义上面for的数据对象的数组
text标签才支持 \n
的换行效果
“双花括号”去js中取变量的意思
数据绑定
小程序中,几乎所有和数据相关的操作都只能使用数据绑定来完成。
动态加载的js文件,调试问题
动态加载的js文件(比如是跳转到公共页面后才有的js),调试时控制台那边的Sources里不会列出这个js文件。
具体需要在跳转的地方断点,然后等待一段时间会自动加载这些js文件(加载时间比较久)
知识点
Flex
Flex:弹性布局,主要作用于容器上
Swiper组件
滑动视图容器–swiper组件
swiper组件的直接子元素只可以是swiper-item,可以放其他组件但会被自动删除。
swiper实现轮播效果,要添加一些属性:
indicator-dots
指示点。Boolean类型,默认是false
autoplay
是否自动播放。Boolean类型,默认是false
interval
切换时间间隔。Number类型,默认5000毫秒
Boolean陷阱
属性vertical="true"
、vertical="aaa"
等都表示“真”。其中的内容是字符串。
要表示“假”,有两种方式:
vertical=""
放空字符串
false里的false被认为是一个Boolean类型的变量,而不是个字符串,从而实现false即是假,true是真的效果。vertical="{{false}}"
放数据绑定
image组件的4种缩放模式和9种裁剪模式
4种缩放模式
scaleToFill
不保持纵横比缩放图片,使图片的宽高完全拉伸至填满image元素
aspectFit
保持纵横比缩放图片,使图片的长边能完全显示出来。即可以完整显示图片
aspectFill
保持纵横比缩放图片,只保证短边能完全显示出来。即长边那部分会发生截取
wiidthFix
宽度不变,高度自动变换,保持原图宽高比不变(0.11.122100版本新增)
9种裁剪模式
top
不缩放图片,只显示图片的顶部区域
bottom
不缩放图片,只显示图片的底部区域
center
不缩放图片,只显示图片的中间区域
left
不缩放图片,只显示图片的左边区域
right
不缩放图片,只显示图片的右边区域
top left
不缩放图片,只显示图片的左上边区域
top right
不缩放图片,只显示图片的右上边区域
bottom left
不缩放图片,只显示图片的左下边区域
bottom right
不缩放图片,只显示图片的右下边区域
例子:
1 | <image class="post-image" src="/images/post/post-4.jpg" mode="scaleToFill"/> |
每个page都有个属于自己的js
页面js文件默认包含了我们可能使用到的代码结构
- 有一个
Page({})
方法, - 参数是一个
Object
对象, - 页面初始数据
data
, - 生命周期
on开头的函数
- 事件处理函数等
5个生命周期
加载 onLoad
监听页面加载,一个页面只会调用一次
显示 onShow
监听页面显示,每次打开页面都会调用
渲染 onReady
监听页面渲染完成,一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互(仅用来监听“第一次渲染”完成)
隐藏 onHide
监听页面隐藏
卸载 onUnload
监听页面卸载
3个小程序特定事件处理函数
onPullDownRefresh
监听用户下拉动作的事件处理函数
onReachBottom
页面上拉触底事件的处理函数
onShareAppMessage
用户点击右上角分享
小程序页面生命周期图解
数据绑定
- 小程序完全抛弃了
DOM
结构(AngularJS
中还有个内置的jQLite
用来支持获取DOM
) - 小程序的脚本逻辑运行在
JSCore
中(JSCore
是个没有DOM
的环境),只能用数据绑定来做数据的相关操作 - 小程序单向数据绑定,从逻辑层传递到渲染层的数据绑定,反之不行。(
AngularJS
是个双向数据绑定) "双花括号"
中的变量名与js
文件中data
对象的属性名称相同
数据绑定有两种:
- 初始化数据的数据绑定,通常写在
Page
方法内data
对象内 - 使用
setData
做数据更新的数据绑定。会引起页面的Rerender
(重新渲染)(可看上图《小程序页面生命周期图解》)
例子:
saleTop.js
中:
1 | Page({ |
saleTop.wxml
中
1 | <!-- first是个对象 --> |
wx:for
wx:for不止可以作用于block标签上,也可以作用于view组件上(但不推荐用在view上,因为view组件通常当做容器或者区域分隔)。
我们希望标签或组件元素是语义明确的。
1 | <block wx:for="{{postList}}" wx:for-item="item" wx:for-index="idx"> |
其中数据源:
1 | Page({ |
wx:if
1 | <view wx:if="{{isRangeTypeOpen}}"></view> |
this与that
- 在
Page({})
里面,this
关键字指代Page({})
整个对象 - 因此可以通过
this
关键字访问或者重新设置Page({})
里data
的变量 - 然而在
loadData
函数中使用了wx.request({})
API这个方法导致在wx.request({})
里没办法使用this
来获取Page({})
对象 - 虽然在
wx.request({})
里没法使用this
获取Page({})
对象,但是可以在wx.request({})
外面先把this
存在某个变量中,所以就有了var that = this
这个声明。此时that
指代Page({})
整个对象,这样子就可以在wx.request({})
里面使用that
访问或者重新设置Page({})
里data
的变量
在javascript
中this
代表着当前对象,会随着程序的执行过程中的上下文改变。
事件
catchtap="methodName"
与bindtap="methodName"
两者的区别:
- 相同点:都是点击函数,点击时触发。
- 不同点:bindtap是冒泡的,catchtap是非冒泡的【冒泡:对应android中的事件向上传递的意思】
小程序中事件分冒泡事件和非冒泡事件
1 | <view id="outer" bindtap="out"> |
1 | out:function(e){ |
bindtap执行结果
点击out view 打印:out bindtap click
点击middle view 打印:middle bindtap click – out bindtap click
点击inner view 打印:inner bindtap click – middle bindtap click – out bindtap click
修改middle view的bindtap为catchtap
点击out view 打印:out bindtap click(因为没有上层元素故而无法向上冒泡)
点击middle view 打印:middle bindtap click(catchtap阻止向上冒泡)
点击inner view 打印:inner bindtap click – middle bindtap click(catchtap阻止向上冒泡)
常见冒泡事件类型
- touchstart 手指触摸动作开始
- touchmove 手指触摸后移动
- touchcancel 手指触摸动作被打断,如来电提醒、弹窗
- touchend 手指触摸动作结束
- tap 手指触摸后马上离开(使用时有两种bindtap、catchtap)
- longtap 手指触摸后,超过350ms再离开
除以上事件,如无特殊申明都是非冒泡事件。
非冒泡事件大多为非通用事件,是某些组件特有的事件。如
<form/>
的submit事件,<input/>
的input事件,<scroll-view/>
的scroll事件等。
模块
模板
缓存
存储数据
wx.setStorageSync("key", value);
设置数据存储,
取出数据
wx.getStorageSync("key")
取出存储的数据
页面传值
通过url带过去
1
2
3
4var url = '../../package-item/item/itemDetail/itemDetail?itemId=' + itemId + '&storeId=' + wx.getStorageSync('storeId') + "&isFromNewPrice=1";
wx.navigateTo({
url: url
})接收(目标页面的js文件中)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19this.getItemSkuInfo.bind(this);
getItemSkuInfo(that) {
return new Promise(function (resolve, reject) {
var skuInfo = "";
...
wx.request({
url: supportRequest + "miniApp/wxItemSkuInfo",
data: {
...,
IsFromNewPrice: that.data.isFromNewPrice//此处直接取到值,并
},
success: function (res) {
...
}
})
})
}
app.js的生命周期
(整个小程序的生命周期)在app.js中:onLaunch启动的一些工作(比如登录等状态校验、权限请求、获取位置信息等、获取用户信息(是否隐式登录)、数据存储)
1 | interface Option { |
(某个页面的生命周期)pages下各自js/Page({})中
1 | interface ILifetime { |
空判断
判断undefined
1 | var tmp = undefined; |
typeof返回的是字符串,有六种可能:”number”、”string“、”boolean“、”object“、”function“、”undefined“
判断null
1 | var tmp = null; |
判断NaN
1 | var tmp = 0/0; |
NaN表示非法,如果把NaN与任何值(包括其自身)相比得到的结果均是false,所以判断某个值是否是NaN,不能使用
==
或===
运算符。
isNaN()通常用于检测
parseFloat()
和parseInt()
的结果,判断结果是否是合法的数字。
判断undefined和null
1 | var tmp = undefined; |
说明:null == undefined
判断undefied、null与NaN
1 | var tmp = null; |
一般不那么区分就使用这个足够
判断空对象
让一个对象一开始设为null,通过判断是否为null即可判断
判断options
是否存在
if(options){//存在} else {//不存在 }
即可
项目配置文件
可以在项目根目录使用 project.config.json
文件对项目进行配置。
问题
微信小程序的Js中调用同一个Js中的另一个函数会报“函数” is not defined
解决:需要在调用的时候加前缀this.
1 | fun_a: function(e){ |
在javaScript中不用加
this.
,直接调用不报错
微信小程序dataset 时属性要为小写
赋值
1 | <view data-myid="{{item.id}}" bindtap="gotoDetails"> |
取值
1 | gotoDetails: function (e) { |
切记data-myid为小写,包含大写会得到 undefined