细节
1['属性1.属性11']的方式拿属性
用法:
['属性.属性.属性']——-即用[]和''包裹属性需要此方式拿上属性的情况
- 1 给data/properties属性的属性赋值 —- 案例1
- 2 在observe中获取属性 —– 案例2
案例
1 | //案例1 |
2 调用API用this. OR wx.
- 组件内调用系统函数用 this. //this.createSelectorQuery()
- 页面内调用系统函数用 wx. //wx.createSelectorQuery()
3 wx:if VS hidden
- 微信官方文档: [wx:if VS hidden]( [https://developers.weixin.qq.com/miniprogram/dev/reference/wxml/conditional.html#wx:if%20vs%20hidden](https://developers.weixin.qq.com/miniprogram/dev/reference/wxml/conditional.html#wx:if vs hidden) )
- wx:if //适用于不频繁的隐藏切换—–消耗大 wx:if = “ 标志位”
- hidden //适用于频繁的隐藏切换 hidden = “ 标志位”
4 typeof判断类型
1 | typeof |
5 setData的回调函数使用
1 | //modelShow、 commShow为data属性 |
6 JSON文件注意事项
- JSON文件中不能写注释
- 引号都必须用:双引号 ""
- 最后一行结尾没有“,”
7 wx:key
- 遍历的数组为对象时 使用对象下的属性
1 | 数组:books[{id:1},{id:2},{id:3},{id:4}] |
- 遍历的数组为数字或字符串时 使用“*this”
1 | 数组:books[1,2,3,4] |
小程序中使用npm
使用步骤:
编辑器右上角:详情–>本地设置–>勾选使用npm模块
任选一个文件夹右击选择在
终端打开- cd到项目根目录下
- 根目录下输入命令:
npm init- 操作成功后会在项目根目录下生成:
package.json文件
- 操作成功后会在项目根目录下生成:
使用npm安装需要的库
- 在终端根目录下输入安装命令即可:
npm install ....
- 在终端根目录下输入安装命令即可:
点击开发者工具中的菜单栏:工具 –> 构建 npm
注意:每次安装依赖后都要点击构建npm
自定义组件
1 observers
components中用于监听properties中属性的变化每次
properties中属性的变化都会触发observers中对应的函数注意BUG 不能在observers中修改properties的值 否则会引起内存泄漏
1 | //例一 |
2 behavior
- Behavior内部与Component内部结构一样
- Behavior编写并导出
1 | let classicBeh = Behavior({ //---------------------------设置行为名称 |
- Behavior导入
1 | import {classicBeh} from '~xxxx.js' |
- 多继承-属性覆盖问题
1 | behaviors:[beh1,beh2,beh3,beh4], //------------------可以导入多个行为,在数组中添加即可 |
小程序端使用云开发
1 调用云函数
- 微信官方文档
wx.cloud.callFunction()
1 | wx.cloud.callFunction({ |
2 调用云数据库
wx.cloud.database()- 简便写法:
const db = wx.cloud.database()
API
- 组件内调用系统函数用 this. //this.createSelectorQuery()
- 页面内调用系统函数用 wx. //wx.createSelectorQuery()
1 本地存储
- 本地存储可以减少数据的请求次数,减少请求量,降低服务端的压力
- 同时用户体验也更好,看以避免数据加载的等待
- 微信开发工具终端
Storage可以查看存储本地的数据
1.1 数据存储本地
- key: 存储数据的键
- data: 存到本地的数据
1 | setMusiclist(){ |
1.2 获取本地数据
1 | 同步 |
2 界面
2.1 导航栏
2.1.1 设置界面标题
1 | wx.setNavigateBarTitle({ |
3 WXML
3.1 取组件
1 | const query = this.createSelectorQuery() //返回对象 |
3.2 获取组件信息
4 基础
4.1 系统
4.1.1 wx.getSystemInfo()
1 | //获取系统相关信息----获取主机的信息 |
5 媒体
5.1 图片
5.1.1 wx.chooseImage()
- 上传图片
5.1.2 wx.previewImage()
- 预览图片
6 设备
6.1 扫码wx.scanCode
- 一维条形码
- 二维码
生命周期
1 组件生命周期
- 微信官方文档: Component生命周期
1.1 自定义生命周期
| 生命周期 | 描述 |
|---|---|
| created | 在组件实例刚刚被创建时执行 |
| attached | 在组件实例进入页面节点树时执行 |
| ready | 在组件在视图层布局完成后执行 |
| moved | 在组件实例被移动到节点树另一个位置时执行 |
| detached | 在组件实例被从页面节点树移除时执行 |
| error | 每当组件方法抛出错误时执行 |
1.2组件所在页面的生命周期
| 生命周期 | 描述 |
|---|---|
| show | 组件所在的页面被展示时执行 |
| hide | 组件所在的页面被隐藏时执行 |
| resize | 组件所在的页面尺寸变化时执行 |
全局变量—app.js
建议设置全局变量的get函数和set函数,不建议直接获取或修改
- 定义全局变量
1 | //app.js |
- 使用全局变量
1 | //在组件或页面引入对全局变量的操作 |
WXS
1 wxml中实现对数据的处理
问题:在wxml中计算价格*数量小数出现问题。
需要新建一个wxs文件
1 | var filters = { |
在wxml文件中引入
1 | <wxs module="filters" src="addmul.wxs"></wxs> |
修改
1 | <view class="price" wx:if="{{item.num > 0}}"> |
为
1 | <view class="price" wx:if="{{item.num > 0}}"> |
2 正则表达式regexp
- 官方文档框架-wxs-数据类型
1 | getRegExp(pattern, flags) |
例子
1 | var reg = getRegExp('\\\\n','g') |
WXSS
1 页面向组件传递外部样式类
- 组件内部设置
- js中设置传入外部样式类的类名 可以传入多个类名 在数组中配置
1 | Component({ |
- wxml中使用外部样式类
1 | <view class="tag-class"></view> |
- 页面向组件传入外部样式
- 在调用组件的wxml中传入 类似数据的传入
1 | <w-tag tag-class="ex-tag"/> |
- 样式写在页面的wxss中
1 | .ex-tag{ |
- 注意:外部样式不能覆盖组件内部原有的样式 所以传入时要用“!important”提高样式级别 确保覆盖
2 阿里iconfont字体图标
页面内使用
iconfont
1 | //1 在app.wxss中引入iconfont.wxss |
组件内使用
iconfont方法1
1
21 将 iconfont.wxss 直接复制到组件文件里
2 组件wxss引入 @import "iconfont.wxss";方法2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17//1 页面组件将样式传递给组件
<w-search iconfont="iconfont" icon-sousuo="icon-sousuo"/>
//2 组件接收
externalClasses: [
'iconfont',
'icon-sousuo',
],
// 3 组件wxml使用
<i class="iconfont icon-sousuo find"/>
//注意事项
在组件内不能修改iconfont的样式
必须再定义class 例如:find
.find {
position: absolute;
}方法3
消除样式隔离
指南—自定义组件—组件模板和样式
1
2
3
4
5Component({
options: {
styleIsolation: 'apply-shared'
}
})3 组件样式特征
1 view
1
2
3view
宽带占满父元素(不变)
高度自适应(变)
2 image
1 | image组件默认宽度300px、高度240px |
组件
复杂组件
movable-area moveble-view组件
组件——视图容器
1 | <movable-view class="movable-view" |
progress进度条组件
1 | <progress |
WXML
1 插槽 slot
1 | //使用多个插槽 配置设置 |
2 textarea
- 获取键盘高度
1 | <textarea bindfocus="onFocus" ></textarea> |
3 小程序原生组件绑定事件不能用”:”
1 | <textarea bindinput="onInput" //bind:input 不能使用 |
4 取消事件冒泡
1 | 用bind: 绑定事件会事件冒泡 |
5 跳转到其他小程序
一个小程序跳转到另一个小程序
两个小程序必须都关联于同一个公众号(订阅号 、服务号)
1 | <navigator target="miniProgram" app-id="wx8ffc97ad5bcccc89" open-type="navigate"> |
6 解析nbsp等
1 | <text decode="{{true}} "> </text> |
开放能力
1 分享小程序
指南—-开放能力—–转发—button
框架—-框架接口—–页面—-Page——onShareAppMessage(Object object)
通过给
button组件设置属性open-type="share",可以在用户点击按钮后触发Page.onShareAppMessage事件,Page.onShareAppMessage
1
2
3
4
5
6
7
8
9
10
11
12<button open-type="share" />
//evenet中的数据由点击button时传入
onShareAppMessage: function (event) {
console.log(event)
const blog = event.target.dataset.blog
return {
title: blog.content,
path: `/pages/blog-comment/blog-comment?blogId=${blog._id}`
//imageUrl: ''
}
},
数据通信
1 点击事件传递数据
1 | //wxml传递数据 |
2 页面跳转携带数据
1 | //传递数据----发出数据页面 |
3 组件与页面之间通信
3.1 组件向页面通信
- 组件向页面传递数据
1 | //组件发出数据 ---- 通过事件携带数据 |
- 组件向页面发出事件
1 | //组件向父页面发出事件 |
3.2 页面向组件传递数据
- js传递
1 | //页面发出数据 |
- wxml传递
1 | //页面传出数据 |
4 页面之间调用函数
1 | //获取pages |
获取用户授权及用户信息
- 获取用户公开信息 用open-data组件
- js中获取用户信息流程:button让用户授权—–>js中再用wx.getUserInfo()API获取用户信息
1 open-data
微信官方文档:组件->开放能力->open-data
只能直接展示在界面上 因为是在WXML中获取的 JS中没有获取信息
只能展示用户自己的相关信息
2 wx.getUserInfo()
获取用户授权信息API: wx.getSetting()
获取用户信息API: wx.getUserInfo()
1
2
3
4getSetting()与getUserInfo() 配合使用
1 用getSetting() 获取用户是否授权的信息
2 若已经授权 则用getUserInfo()获取用户信息
3 若未授权 则用下方的button 弹出获取用户的权限的弹出框
- 使用前提: 必须是用户已经授权之后才可以调用这个接口 所以先用wx.getSetting获取用户授权情况 判断之后再使用wx.getUserInfo()
3 button
点击button 弹出获取用户权限的弹出框
1 | <button class="login" |
4 login云函数获取openId
Cloud.getWXContext()
通过小程序自带的login云函数获取openID
返回值只有openId 和appId
音乐播放开发
1 | //1 获取全局唯一背景音频管理器 |
订阅消息
微信官方文档:指南->开放能力->消息->订阅消息
- 订阅消息API: wx.requestSubscribeMessage()
- 云函数调用API: subscribeMessage.send
- subscribeMessage.send 开发文档中 有关于传入数据的数据类型的要
1 | 1 wx.getSetting() 获取获取用户对相关订阅消息的订阅状态。 |
小程序码
- 建立云函数、生成二维码(但是是二进制格式)
- 在云函数中将二进制格式的二维码上传到云存储,上传成功返回结果即是图片格式二维码
- 云函数中将图图片格式return出去
- 小程序端调用云函数获取二维码
生成二维码API:
cloud.openapi.wxacode.getUnlimited官方文档:getUnlimited
云函数部分
1 | //getQrCode/index.js |
- 小程序端部分
1 | wx.cloud.callFunction({ |
小程序进阶
1 渲染页面的技术选项
纯客户端原生技术(ios, java)
纯web技术(html, css. js)
渲染层与逻辑层同一个线程–低效
用客户端原生技术与web技术结合的混合技术(Hybird)
渲染层与逻辑层不同线程—–高效
2 小程序渲染层与逻辑层交互原理
- 不能频繁使用setData(): 避免多次逻辑层<—->系统层<—->渲染层 占用资源 出现卡顿
- 不需要展示在界面的数据定义在data外
3 小程序版本更新管理
API——-基础——-更新
//模拟器测试
//app.js——-onLaunch函数中调用
1 | //检查版本更新情况并更新 |
4 小程序性能与体验优化
4.1 体验评分
- 调试器——-Audits(手动测试每个功能)
- 详情—–本地设置—–自动运行体验评分(调试过程中就已经进行了评测)
4.2 注意事项
- 所有资源请求建议使用HTTPS (HTTP是明文的 可能出现数据被篡改)
- 及时回收定时器
- 避免使用:active伪类来实现点击态(小程序中 滑动过程中点击态不会消失 小程序中建议使用hover)
- 滑动区域开启惯性效果 (安卓自带惯性效果 苹果上要有一下设置:-webkit-overflow-scrolling:touch)
- 避免出现JavaScript异常
- 避免短时间内发起太多的图片请求(使用iconfont字体图标)
- 避免短时间内发起太多请求
4.3 setData注意事项
- 避免setData的数据过大(1M以内)
- 避免setData调用过于频繁
- 不需要展示在界面的数据定义在data外 以减少setData的使用
5 小程序上线审核流程
微信公众平台——管理—–版本管理
开发版本——>审核版本——–>线上版本
5.1 上传成体验版(开发版本)
微信开发工具——-右上方“上传”
版本号含义
1
2
3
40.0.0
//第一位 大功能修改
//第二位 小功能修改
//第三位 Bug修改查看代码量的大小
微信开发工具——–右上方“详情”——基本信息——本地代码
小程序上传代码包要求小于2M
6 关于服务类目
微信开发文档—-上方“介绍”——-产品定位及功能介绍——小程序信息完善及开发前准备—–小程序开放的服务类
小程序端HTTP请求封装
1 封装HTTP请求(callback)
对比1封装HTTP请求(callback)与 2封装HTTP请求(promise) 体会promsie的优势
1 根目录下-config.js——-封装基础网络请求信息
1
2
3
4
5
6const config = {
api_base_url: 'http://hhhhhhh.pro/v1/',
appkey: "K57S1kGd4CLBz2dw",
}
export {config}2 utils/http.js———-封装wx.request()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56import {config} from '../config.js'
const tips = {
1: '抱歉,出现了一个错误',
1005:'appkey无效,请前往www.7yue.pro申请',
3000:'期刊不存在'
}
class HTTP{
request(params){
// 参数params{url, data, method,}
if(!params.method){
params.method="GET"
}
wx.request({
url:config.api_base_url + params.url,
method:params.method,
data:params.data,
header:{
'content-type':'application/json',
'appkey':config.appkey
},
success:(res)=>{
let code = res.statusCode.toString()
if (code.startsWith('2')){
//--------------------将数据返回给调用方的回调函数----------------------
//---- params.success--->判断是否传入了回调函数 若未传入则不返回数据------
params.success && params.success(res.data)
}
else{
let error_code = res.data.error_code
this._show_error(error_code)
}
},
fail:(err)=>{
this._show_error(1)
}
})
}
//服务器异常处理函数 传入参数为错误码-----这部分处理根据具体情况确定
_show_error(error_code){
if(!error_code){
error_code = 1
}
const tip = tips[error_code]
wx.showToast({
title: tip?tip:tips[1],
icon:'none',
duration:2000
})
}
}
export {HTTP}3 models/xxxxx.js—————-继承封装的HTPP继续封装具体方法
- 一般一个页面再封装一个类 —>类下封装获取不同数据的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27import {HTTP} from '../utils/http.js'
class ClassicModel extends HTTP { --------classic 为一个页面名
getLatest(sCallback){ ------------------getLatest()为定义的具体方法
this.request({
url: 'classic/latest',
success:(res)=>{ ---------通过utils/http.js中params.success(res.data)传回的数据
sCallback(res) --------------------将数据返回给调用方的回调函数
}
})
}
}
export {ClassicModel}
import {HTTP} from '../../utils/http.js'
let http = new HTTP()-----------------注意实例化
http.request({
url: 'classic/latest',
success:(res)=>{
console.log(res)-----------通过utils/http.js中params.success(res.data)传回的数据
}
})4 页面中调用models/xxx.js 中的类下的方法 —–实例化类
1
2
3
4
5
6
7import {ClassicModel} from '../../models/classic.js'
let classic = new ClassicModel()-----------------注意实例化
classic.getLatest((res)=>{
console.log(res)-----------通过models/xxx.js中sCallback(res)传回的数据
})
2 封装HTTP请求(promise)
对比1封装HTTP请求(callback)与 2封装HTTP请求(promise) 体会promsie的优势
1 根目录下-config.js——-封装基础网络请求信息
1
2
3
4
5
6const config = {
api_base_url: 'http://bl.7yue.pro/v1/',
appkey: "K57S1kGd4CLBz2dw",
}
export {config}2 utils/http.js———-封装wx.request()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61import {config} from '../config.js'
const tips = {
1: '抱歉,出现了一个错误',
1005:'appkey无效,请前往www.7yue.pro申请',
3000:'期刊不存在'
}
class HTTP{
//提供给外部
request({url,data={},method='GET'}){ //注意传参用{}、并且写出每个参数
return new Promise((resolve,reject)=>{------------//通过return一直将promise对象返回
this._request(url,resolve,reject,data,method)
})
}
//提供给内部
_request(url,resolve,reject,data={},method='GET'){
wx.request({
method,
data,
url:config.api_base_url + url,
header:{
'content-type':'application/json',
'appkey':config.appkey
},
success:(res)=>{
let code = res.statusCode.toString()
if (code.startsWith('2')){
resolve(res)-------------1
}
else{
reject()---------------1
let error_code = res.data.error_code
this._show_error(error_code)
}
},
fail:(err)=>{
reject()------------------1
this._show_error(1)
}
})
}
//服务器异常处理
_show_error(error_code){
if(!error_code){
error_code = 1
}
const tip = tips[error_code]
wx.showToast({
title: tip?tip:tips[1],
icon:'none',
duration:2000
})
}
}
export {HTTP}3 models/xxxxx.js—————-继承封装的HTPP继续封装具体方法
- 一般一个页面再封装一个类 —>类下封装获取不同数据的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14import {
HTTP
} from '../utils/http-p.js'
class bookModel extends HTTP{
getHotList(){
return this.request({---------------------//通过return一直将promise对象返回
url:'book/hot_list'
})
}
}
export {BookModel}4 页面中调用models/xxx.js 中的类下的方法 —–实例化类
1
2
3
4
5
6
7
8
9
10
11import {BookModel} from '../../models/classic.js'
let bookModel = new BookModel()-----------------注意实例化
const hotList = bookModel.getHotList() ---hotList即返回的promise对象(resturn回来的)
hotList.then(
(res)=>{---------------------------------------res即resolve()的回调函数
console.log('book-hotlist',res)
},
(error)=>{------------------------------------error即reject()的回调函数
console.log(error)
})
上拉触底加载封装
封装的
behavior相当于对列表数据的一个管理注意事项
- 上锁 避免用户操作过快导致发送重复的网络请求 当发送网络请求时上锁 请求结束后解锁
- 列表数据全部加载完成判断 若列表数据全部加载完成 则不再发送获取更多数据的网络请求 避免消耗过多资源
不使用behavior
1 | data: { |
- 使用behavior
1 | const paginationBev = Behavior({ |