1.开发前的准备工作
1.1 申请AppID
- 登录微信公众平台: mp.weixin.qq.com
- 进入之后,点击右下角'小程序', 之后下滑进行注册
- 注册完毕后进行登录. 点击右侧'开发', 之后点击上边的'开发设置'
- 下边就可以看到AppID 和 AppSecret
1.2 开发工具
- 官方微信Web开发者工具, VSCode,Hbuilder
- 右上角'文档'--->点击'工具'--->'微信开发者工具'--->下载稳定版
- 新建项目 选择一个空的文件夹--->完成GitHub版本管理
1.3小程序码
- 右上角的'工具'
- 输入已经上线小程序的AppID, 方可获取小程序码
2. 基础
2.1应程序结构
- 最上层app-> 多个Page页面 -> 多个组件component
- app层有 app.js, app.wxss, app.json
- page层有 .js, .json, .wxss, .wxml
- component有 .js, .json, .wxss, .wxml
2.2 数据绑定
- wxml中用插值语法{{ name }}
- js中 data:{ name: '张三' }
2.3 列表渲染
<view wx:for="{{ datalist }}"> {{item}} </view>
2.4 事件监听
2.5 配置小程序
- project.config.json: 项目配置文件,比如项目名称,appID等等
- sitemap: 小程序搜索相关的
- app.json: 全局配置( pages,windows,tabBar,netWork......) 官方文档-全局配置
- page.json: 页面配置 官方文档-页面配置
2.6 小程序的双线程模型
- webView执行wxml和wxss
- jsCore执行js代码
3. 小程序的App()和Page()
3.1 小程序的启动流程
- 下载小程序包-->启动小程序-->
- 解析app.json-->执行app.js来注册App()-->会执行App()内部的周期函数-->
- 加载自定义组件-->注册自定义组件-->
- 加载各个页面-->解析个页面的.json-->
- 渲染层webView加载 .wxml-->逻辑层.js注册Page()函数-->执行Page()内部的生命周期函数
3.2 在App()中可能做的事情
- 监听生命周期函数
- 判断小程序的进入场景
- 定义全局变量( App()是单例对象 )
3.3 在Page()中可能做的事情
- 监听生命周期函数
- 初始化数据
- 监听wxml页面中的事件
- 监听一些其他事件:
- 页面滚动onPageScroll()
- 监听页面滚动到底部onReachBottom() 下载加载
- 上拉刷新 onPullDownRefresh()
- 生命周期图

4. 小程序的组件
4.1 Text组件
- 类似于span标签,是行内元素
- selectable属性:是否可被选中
- space属性: 显示连续空格, nbsp默认的空格 emsp中文空格 ensp半个中文的大小
- decode属性:
会把文本中的 > 解码成 大于号 >
4.2 Button组件
- size属性: 大小
- type属性: 按钮颜色
- plain属性: 镂空效果
- disabled属性: 是否禁用
- loading属性:
- hover-class属性: 按钮按下的样式
- open-type属性:
4.3 view 组件
- hover-class属性: 按下时的样式
- hover-stop-propagation: 阻止冒泡
- hover-start-time: 按下后多久出现点击状态
- hover-stay-time: 手指所开后状态保留时间长短
4.4 image组件
- 可以写成单标签,也可以写成单标签
- 默认有自己的大小,320*240
- 它是行内块元素
- src属性: 本地地址/远程地址
- lazy-load属性: 图片懒加载
- bindload事件,图片加载完成自动触发的事件
- show-menu-by-longpress
- mode缩放模式
4.5 input组件
- value属性
- type属性: 决定键盘类型
- password属性
- placeholder属性
- disabled属性
- maxlength属性: 最大长度
- confirm-type属性: 设置键盘右下角的文字
- bindinput事件: 正在输入
- bindfocus事件: 获得焦点
- bindblur事件: 失去焦点
4.6 scroll-view组件
- scroll-x属性: 水平滚动
- scroll-y属性: 垂直滚动
- bindscroll事件: 发生滚动时自动触发的事件,可以打印事件详情
4.7 共同属性
- id
- class
- style 设置内联样式
- hidden 隐藏
- data-* 自定义属性
- bind* 和catch 事件
5. 小程序的样式
5.1 页面的三种样式
5.2 支持的选择器
5.3 尺寸单位
- 750rpx = 屏幕宽度(iPhone6宽度为375px), 则1rpx等于0.5px
- iPhone5是1rpx= 0.42px
- iPhone6 Plus是 1rpx= 0.552px
- width: calc(750rpx * 100 / 375); 在宽度为375个px的屏幕中,设置某个元素的width值为100px
5.4 样式导入
- 在页面文件夹下新建style文件夹,于其中写入.wxss文件. 在页面中 @import ' ./style/box1.wxss ';
- 也可全局新建style文件夹, 然后在app.wxss文件夹中导入
5.5 官方样式库
6. 语法
6.1 wxml基本格式
- 类似于Html代码
- 必须严格闭合标签
- 大小写敏感: (如class和Class是不同的属性)
6.2 Mustache语法{{}}
- 绑定变量
- 支持字符串拼接
- 三目运算
- 绑定属性也使用mustache
6.3 条件和hidden
- wx:if="{{ score>=90 }}"
- wx:elif="{{ score>= 60 }}"
- wx:else
- hidden属性:显隐
6.4 循环
遍历数组 <view wx:for="{{ [a,v,f,o,e,d] }}"> {{item}} {{index}} </view>
遍历字符串 <view wx:for="aweyurtpasdjhf"> {{item}} {{index}} </view>
遍历数字 <view wx:for="{{ 13 }}"> {{item}} {{index}} </view>
- block临时标签
- 最终不会渲染出来的, 类似于vue的template标签
- 一般接受控制属性, wx:for, wx:if等等.
- class, id 等属性不要在block标签中写
- 给item和index 起名字
<view wx:for="{{movies}}" wx:for-item="m" wx:for-index="i"> {{m}} {{i}}</view>
- 循环中加: wx:key="{{index}}",key主要作用是高效更新DOM, 最好用id作为key的
6.5 模板语法 template标签
<template name="content">
<button> 按钮 </button>
<button> {{ btn_text }}</button>
<view>hello world </view>
</template>
模板包裹的内容在没有使用前,是不会进行任何的渲染的.
模板定义完,就是让我们用的
如下是使用的过程:
<template is="contentItem" data="{{btn_text: value2}}"/>
于.js文件中data内 设置value2的值
<import src="模板文件的路径" /> `
不支持循环导入,乙里导入甲,丙里导入乙. 丙中无法使用甲.
include可以将目标文件中除了 <template/>和<wxs/>外的整个代码引入, 相当于拷贝到include位置. include支持循环导入.
include模式非常简单,就是简单的代码替换.不存在作用域,也不像template需要data传递变量. 它只是简单的将代码拿出去,用的时候再拿回来. 作用是单纯的简化页面.
7. wxs模块
7.1 基础
- wxs(WeiXin Script) 是小程序的一套脚本语言,结合wxml,可以构建出页面结构
- WXS与JavaScript是不同的语言,有自己的语法,并不和JavaScript完全一致.
- wxml中是不能直接调用Page/Component中定义的函数的
7.2 wxs的限制和特点
- wxs的运行环境和其他JavaScript代码是隔离的,wxs中不能调用其他JavaScript文件中定义的函数,也不能调用小程序提供的API
- WXS函数不能作为组件的事件回调
- 用处: 当我们在页面中有些数据需要处理,而我们.js文件中的函数是不能对他进行处理的. 这时我们就可以用wxs来进行处理了
7.3 wxs如何定义使用
<wxs module="info">
var name = 'zhangsan'
var sum = function(a1,a2){
return a1 + a2
}
module.exports = {
name: name,
sum: sum,
}
</wxs>
<view> {{info.message}} </view>
定义在单独的.wxs文件中,再使用<wxs src="">标签进行导入,不能使用绝对路径
8. 事件
8.1 常见公共事件
- bindtap=" " 或者 bind:tap="" 点击事件
- catchtap=" " 或者 catch:tap="" 点击事件
- touchstart 开始触摸
- touchmove 开始移动
- touchcancel 触摸突然被打断 (如突然出现弹窗,突然来电)
- touchend 触摸结束
- longpress 长按事件 350ms以上
8.2 某些组件会有自己的事件
如<input>有 bindinput/bindblur/bindfocus
如<scroll-view>有 bindscrolltowpper/bindscrolltolower
8.3 事件对象的分析
| 属性 | 类型 | 说明 | 备注 |
|---|
| type | String | 对事件类型的描述 | 我的备注 |
| timeStamp属性 | Integer | 页面打开到触发事件 所经历的时间 | |
| target属性 | Object | 产生事件的组件, 其一些属性的集合 | |
| currentTarget | Object | 响应事件的组件, 其一些属性集合 | |
| detail | Object | 额外的信息 | |
| touches | Array | 触摸事件, 停留在屏幕中的触摸点数组 | |
| changedTouches | Array | 触摸事件,记录增加(或减少)的触摸点的数组 | |
8.4 事件的传递参数
- data-index2="{{index}}"
- 从data.currentTarget.setdata.index2来取这个值
8.5 事件冒泡和捕获
- capture-bind:tap 监听事件捕获
- bind:tap 监听事件冒泡
- capture-catch:tap 在事件捕获阶段,阻止向内传递
- catch:tap 在事件冒泡阶段,阻止向外传递
- (以上冒号可以省略)
9. 组件化开发
9.1 基本使用
- 定义组件 新建components文件夹, 内部建子文件夹,下设四个文件
- 在自定义组件中.json文件下,component: true. 只有该字段为true才能是一个组件
- 引用处: "usingComponents": {"起标签名": "/组件路径"}
- 标签名只能是小写字母,数字,中划线和下划线
- 一个自定义组件可以引入另一个自定义组件
- 自定义组件起名时不要以wx-作为前缀
- 很多页面要引入的话, 可以在app.json文件中,将其注册成全局组件
- template模板只有wxml和wxss两个部分,而且两个部分要分别引入
- 自定义组件由.json .js .wxml .wxss 组成,不需要分别引入
9.2 组件里的样式
- 组件里边定义的样式,不会对引用它的页面 造成影响, 同样页面的样式也不会影响组件
- 在组件里边,不能使用id选择器,属性选择器,标签选择器
- 如果想相互影响,在组件.js文件下,options:{ styleIsolation: "isolated" }
- "isolated"是默认值,是隔离的.
- "apply-share"这个是不隔离,页面样式可以影响组件
- "share" 这个值是不隔离,组件也可以影响页面,页面也可以影像组件
9.3页面给组件传值
(1)页面给组件传数据
于组件的.js文件中properties: {name3: String}
或者properties: {
name3: {
type:String,
value: "默认值",
observer: function(new, old) {}
}
}
于页面引用处的标签加name3属性,并赋值
(2)页面给组件传样式
在组件的.wxml文件中使用box1这个样式
在组件的.js文件中externalClass: ["box1","box2","box3"]
在父页面引用处: box1="box1class"
在父页面引用的.wxss文件中编写.boxclass{ color: #f00 }
(3)页面给组件传标签, slot插槽
单个插槽
在组件中用<slot/>
在引用的页面<自定义组件> 此处写入,想传给组件的HTML结构 </自定义组件>
多个插槽:
在组件.js文件中 options: { multipleSlots: true }
在组件中用<slot name='slot1'/>
在引用的页面<自定义组件 slot="slot1"> 此处写入,想传给组件的HTML结构 </自定义组件>
9.4 组件给页面传值
组件给页面传事件:
在组件中
methods: {
handleEvent() { this.triggerEvent('myEvent',{数据},{options})}
}
注: handleEvent是自己随便起的名字. 这个名绑定到组件的.wxml中
注: myEvent是自己随便起,这是传递到外边页面的事件名.
页面中 <自定义组件 bind:myEvent="handleEvent3" />
在页面.js文件中实现handleEvent3事件
如果子组件在事件中传递了数据,在页面.js文件handleEvent3事件中打印event,打印后的detail中就可以拿到此数据
9.5 页面通过组件的引用,修改组件内部的值
获取组件对象
在父页面的.js文件中用 this.selectComponent('.class/#id')来获取组件对象. 然后通过组件对象来更改这个组件内部的值.
最好通过调用组件内部的方法来更改组件内部的值.
9.6 Component构造器
(1)内部基本内容
Component{
properties:
data:
methods:
options:
externalClasses: ['box1','box2']
observers: {} 监听data和properties改变,只能拿到newValue
生命周期
}
(2)组件监听页面的生命周期
pageLifetimes: {
show(){},组件所在页面显示出来
hide(){},组件所在页面隐藏起来
resize(){},组件所在页面大小改变
}
(3)组件监听本身的生命周期
lefttimes: {
created() {},组件创建出来
attached() {},添加到页面
ready() {}, 组件被渲染出来
moved() {},组件移动到另一个节点内
detached() {},组件被页面移除
}
10. 小程序的API
10.1 网络请求
- 先配置合法域名列表: 小程序后台-->设置--->开发设置-->服务器域名
测试阶段: "详情"---->"不校验合法域名....."
可以用这个网址http://httpbin.org/ 来模仿各种请求的方式
wx.request({
url: 'http://......:8080/index',
success: (res) => console.log(res),
data: {发网络请求时要传的参数},
method: post / get, // post请求参数不允许拼接到url上边
header: 设置请求头..比如访问某些网页,需要往header中加上token才可以访问,
dataType: 返回数据的格式,
responseType: 相应的数据类型,
fail: 失败回调,
complete: 完成时就会回调
})
10.2 封装网络请求
(1)跟目录新建service文件夹,内部新建一个network.js文件:
retutn new Promise( (resolve,reject) => {
wx.request({
url: options.url,
method: options.method || 'get'
data: optionss.data || {},
success: res => resolve(res)
fail: err => reject(err)
})
} )
(2)使用处导入这个文件即可 import request from '../../service/network.js'
使用自定义的函数: request({ url:"", data: "", ...}).then(res=>console.log(res,"获取
成功回调").catch(err=>console.log(err,"获取失败回调")
这种链式方式不会出现回调地狱.
10.3 展示弹窗
(1)
wx.showToast({
title: '你好',
duration: 时间,
icon: 图标,
mask: true, 蒙版
})
(2)
wx.showModal({})
(3)
wx.showLoading
(4)
wx.showactionSheet({})
10.4 页面分享
- 有这个函数就可以分享: onShareAppMessage: options => {
title: 转发标题,
path: 转发路径,
imageUrl: 转发时的封面,默认是本页截图
}
<button size='mini' open-type="share">分享1</button> 此时这个按钮也有分享的功能
10.5 小程序的登录流程
- 49 ---> 图
- wx.login() 从微信的服务器请求一个code
- 开发者服务器通过一个接口把 code + AppID + AppSecret 传给微信服务器
- 这时微信服务器会给我们传回来两个东西, session_key和openid
- 这时就可以把openid当成用户的唯一标识
- 可以设置自己的登录方式: 账号+密码
- 把openID + 账号 + 密码 存到表中, 生成token令牌传递给用户. 小程序里边有个storage, 把令牌保存到storage中.
在App({ })同级: const TOKEN = 'token', 定义字符串常量
onLaunch() {
const token = wx.getStorageSync(TOKEN)
if (token && token.length !== 0 ){
this.check_token(token)
}
else{
this.login3()
}
},
login3() {
wx.login({
success: (res) => {
const code = res.code;
wx.request({
url: '...',
method: 'post',
data: { code },
success: (res) => {
const token = res.data.token
this.globalData.token = token
wx.setStorageSync(TOKEN,token)
}
})
}
})
}
check_token(token) {
wx.request({
url: '',
method: 'post',
header: {
token
},
success: (res) => {
if (!res.data.errCode) {
this.globalData.token = token
}
else {
this.login
}
},
fail: err => {
}
})
}
10.6 页面跳转
(1)
<navigator url='./...'>跳到某页</navigator>
open-type属性:
navigate默认值,保留当前页跳转
redirect关闭当前页面跳到非tabbar页面,
switchTab跳到tabbar页面
reLaunch 关闭所有页面之后跳转
navigateBack 自定义返回
delta属性: 2返回两个层级
(2) 页面跳转时传数据
在url后边 ?name=lisi&age=18
在目标页面onLoad(options) { console.log(options) }
(3) 目标页面往回传数据
onUnload() {
const pages = getCurrentPages()
const home = pages[pages.length - 2]
this.setData({age: 30})
}
- 通过事件接口实现页面跳转
- wx.navigate
- wx.redirectTo
- wx.switchTab
- wx.reLaunch
- wx.navigateBack