微信开发工具常用快捷键
- Ctrl + D: 选中匹配
- Shift + ↑/↓: 移动一行代码
- Shift + Alt + ↑/↓: 向上或下复制一行代码
- Shift + Alt + F: 代码格式化
- 输入一个标签单词,然后按 tab 可自动补全
- 输入 api 前缀,然后按 tab 往往可以补全常用参数
新建页面的方法
在 app.json 文件下 pages 数组的页面路径,如果指向一个不存在的页面,那么 MINA 框架会自动创建这个页面的 4 个文件。
利用这点,我们可以快速创建页面且不会出 bug
相对路径与绝对路径
- '/': '/'开头代表根目录,常用在 images 路径设置。比如 <image src="/images/icon/wx_app_like.png"></image>
- ‘./’: './' 表示当前目录,可以省略。比如 './childIndex1/child' 可以写成 'childIndex1/child'
- wx.navigateTo 的页面路径,采用相对路径,且不要加上文件扩展名。比如 wx.navigateTo({url: '../post/post'})
- template 引用模板,采用相对路径,且需要文件扩展名。比如 <template is="postItem/postItem.wxml">
- require 引用 js 模块,采用相对路径,且需要文件扩展名 js。(注意不可以用绝对路径,也不可以不加 .js)。比如 require('../../data/data.js')
- tab 选项卡,pagePath, iconPath, selectedIconPath 采用绝对路径,不需扩展名。比如 "pagePath": "pages/post/post"。(注意不要用 '/' 开头)
小程序尺寸与 rpx 含义
官方建议以 iPhone6 作为标准做设计图。它的特点是:
- 宽度 750rpx
- 设计图里 1rpx = .5px
只记结论的话:rpx 是相对单位,px 是长度单位。在 iphone6 设计稿里,1p = 2r
如何读懂模拟器的分辨率选项?
先介绍一些概念:
逻辑像素:px
物理像素:rpx(PS 设计图里的像素)
比如选择一种机型,给出的分辨率信息是: 375x667; Dpr: 2
意思是:屏幕宽 375px, 高 667px,其中 1px = 2rpx
全局样式文件 app.wxss
app 为名的文件都与全局有关
app.wxss 用途,比如说需要设置整个小程序的默认字体,最有效的做法是:
text {
font-family: Microsoft YaHei;
}
学习 API 的方法
就是一个字,“试”
比如 window 这个配置项,只需将其他几个属性加入到 window 中,再更改几个可能的属性值,就可以立刻预览属性值效果。通过实践+观察就能掌握。
就像掌握一个不熟悉的软件或上手一个新 App, 所有按钮和选项多点多试就熟悉了。
小程序的 Boolean 坑
有这样一个问题,配置一个真值属性,比如 swiper 组件的 vertical 值,当我们写
<swiper vertical="false">
...
</swiper>
时,其实 vertical 的值是 true。不仅如此,只要字符串非空,该属性一直为真。设置 vertical = "aa", vertical = "bb" 都一样。
正确写法是:
<swiper vertical="{{false}}">
...
</swiper>
小程序里没有标签,只有组件
比如最基本的 <view>, <text>, <image>
比如扩展的 <swiper>,<input>
比起 html 各种杂七杂八的标签,可以说是相当简洁
一般来说都是双标签,有一些例外比如
- <input />
- <import />
image 组件的 4 种缩放模式和 9 种裁剪模式
设置 image 组件的 mode 属性即可
缩放模式
- scaleToFill: 不保持横纵比例强行拉伸,直至填满
- aspectFill: 使长边完全显示(也就是说可以完整显示全图,但是会有黑边)
- aspectFit: 使短边完全显示(也就是说没有黑边,但是不会完整显示全图)
- widthFit: 宽度不变,高度自动变化
裁剪模式
直观讲,以容器尺寸为裁剪框,hover 图片。裁剪框有 9 种可选位置
- top
- bottom
- center
- left
- right
- top left
- top right
- bottom left
- bottom right
裁剪模式虽然多达 9 种,却不难记忆,它们的位置可以用 “米” 字来想象。假设桌面上一张图片,用相框 hover 上去。
“米” 字的 “十” 部分代表相框位于上下左右中 (top, bottom, left, right, center)
“米” 字的叉部分代表相框位于四个对角(top left, top right, bottom left, bottom right)
navigateTo, redirectTo
区别:
- navigateTo 将保留当前页面,然后跳转
- redirectTo 将关闭当前页面,然后跳转
直观体验,就是 navigateTo 跳转后页面可以返回,redirectTo 没有后退按钮
注意一点:
onHide 称为隐藏页面,onUnload 称为卸载页面
navigateTo 触发原页面的 onHide 不触发 onUnload
redirectTo 触发原页面的 onUnload 不触发 onHide
很容易理解,如果是为了节省内存,我也会这么设计
顺便一提:
A 页面 navigateTo B 页面,那么称 A 为父页面,B 为子页面
A 跳到 B,然后 B 点返回跳到 A,这时会触发 B 页面的 onUnload 函数,也就是说会卸载子页面
应用场景就是子页面上的音乐播放,如果子页面上点了一首歌,然后返回父页面,这时音乐会停止。解决办法就是用 playBackgroundAudio 全局播放
小程序的事件冒泡
结论是:catchXX 不冒泡,bindXX 冒泡
模板
意义是减少重复的 wxml 和 wxss 代码,当发现模式重复的时候就可用
三部曲:
第一步,新建文件夹,创建 wxml 和 wxss 文件
第二步,编写模板
第三步,引用模板
编写模板的格式是:
<template name="模板名">
<view>...</view>
</template>
引用模板的格式是:
<import src="模板路径">
...
<template is="模板" data="{{传入模板数据}}">
注意模板路径采用相对路径,且需要文件扩展名。比如 <template is="postItem/postItem.wxml">
关于模板使用,有一个 trick,叫 "消除模板对外部变量名的依赖"
举个例子,如果我们引用页写入 <template is="xx" data="{{item}}">
那么模板页所有数据绑定都必须 {{item.xx}}, {{item.yy}}
每次写模板都要想传入参数名字并且与调用接口遵守约定太蠢了,一个好办法是用展开运算符 ...
还是那个例子,我们这样写 <template is="xx" data="{{...item}}">
模板页所有数据绑定直接 {{xx}}, {{yy}} 就行了
最关键的一点,现在我们引用页传入数据的参数可以随便改。 A 页写 data="{{...item1}}" ,B 页写 data="{{...item2}}" 都可以,这增加了模板的泛用性
小程序的异步方法
几乎所有小程序的异步 API 方法都包含这 3 个方法: success, fail, complete
比如 wx.setStorage(object)
编写缓存数据库类
缓存,和数据库是两个概念。
缓存就是开发者工具的 Storage,目的一是提高页面性能,二是在没有后端接口的时候 mock 接口数据
数据库类是非常关键的一块,意义在于使我们页面涉及后端的所有操作能用一句话完成,简洁高效地完成 MVVM 的 "更新 Model" 任务
缓存数据库,指的是建立在开发者工具 Storage 上的数据库
class DBPost {
constructor(url) {
this.storageKeyName = 'key'
}
// 获取全部数据
getAllData() {
let res = wx.getStorageSync(this.storageKeyName)
if(!res) {
// ../data/data.js 是预先准备的数据文件,在没有缓存的时候初始化数据
let res = require('../data/data.js').postList
wx.setStorageSync(this.storageKeyName, res)
}
return res
}
}
export { DBPost }
具体到文章数据库,因为有 "根据 id 号获取文章详情","点赞","收藏" 等,为了方便增删改查如下:
class DBPost {
constructor(url, itemId) {
this.storageKeyName = 'key'
this.itemId = itemId
}
// 查:获取全部数据
getAllData() {}
// 查:根据 id 获取文章详情
getItemById() {
let allData = this.getAllData()
for(let i=0; i<allData.length; i++) {
if(this.itemId === allData[i].id) {
return {
idx: i,
data: allData[i]
}
}
}
}
// 改:根据 id 修改收藏,点赞,阅读,评论数据
updateItemById() {
// 获取必要数据
let allData = this.getAllData()
let item = this.getItemById()
let {data, idx} = item
data.xxxx 属性修改
data.yyyy 属性修改
// 更新缓存数据库
allData[idx] = data
wx.setStorageSync(this.storageKeyName, allData)
return allData
}
}
不要在 template 上注册事件
<template catchtap="onTapToDetail" is="postItemTpl" data="{{...item}}"> (x)
<view catchtap="onTapToDetail"><template is="postItemTpl" data="{{...item}}"></view> (√)
原因是 template 标签是一个占位符,编译后会被它的内容取代从而在 wxml 中不可见
页面中传递参数的 3 种方式
页面间的通信,有以下几种参数传递方式:
- 使用全局变量(app.js)
- 使用缓存
- 通过页面导航 url 的 query 参数
即:url,缓存,全局变量
获取页面参数取值
通过页面里 onload 函数的 options 参数来获取
设置编译后的初始化页面
这是 IDE 的一个便利功能,一般编译后直接进入小程序首页(pages 数组第一项)
可以通过编译选项修改
收藏,点赞,评论功能通用套路
跟 vue 一样
onCollectionTap(event) {
// 更新 M
// 更新 VM
}
例子
onCollectionTap(event) {
// 更新 M(一句话完成,如果不是,就修改缓存数据库类直到是)
let newData = this.dbPost.collect()
// 更新 VM
this.setData({
post.collectionStatus: newData.collectionStatus,
post.collectionNum: newData.collectionNum
})
}
本地缓存的重要性
提供本地的 key&value 缓存机制是小程序的一大特点,善用本地缓存可以极大地改善客户端体验与服务器性能。
在一个高性能产品中,缓存的重要性是不言而喻的。建议将本地缓存视作一个 key&value 数据库,并封装一些类和公共方法,提供给项目的各个调用方。最好不要让 getStorage, setStorage 充斥各角落
util 文件夹
新建 util 文件夹及 util.js,在上面编写公共方法
- 在 Date 原型链上添加 format 方法
- 日期计算
......
input 事件
- bindinput
- bindconfirm
- bindfocus
- bindblur
注意这四个 bind 事件不同于之前的 catch/bind规律,它们是非冒泡的
在 MVVM 框架实现 CSS3 动画
简单说,就是通过 viewModel 控制类的添加与删除
<view class="file {{deleteIdx===idx? 'deleting': ''}}"></view>
解决滑动卡顿问题
.xx {
-webkit-overflow-scrolling: touch;
}
跳转到 tab选项卡的坑
需要特别注意的是,wx.redirectTo 和 wx.navigateTo 无法跳转到带 tab 选项卡的页面
只能用 wx.switchTab 跳转
同理,wx.switchTab 也无法跳转到不带 tab 选项卡的页面
实现页面下拉刷新的 "三部曲"
第一步:在页面的 json 文件中配置 enablePullDownRefresh
第二步:在页面的 js 文件中编写 onPullDownRefresh 函数
第三步:在回调函数中调用 wx.stopPullDownRefresh 函数
json 中的 backgroundColor 配置的是哪里的颜色
真机小程序,向下拉动后,在导航栏和页面间会出现一块空白,backgroundColor 定义这块的颜色
上滑加载更多数据
onReachBottom
注意这里要使用数据绑定的思维
追加 (x)
重新绑定和渲染整个数据数组 (√)
let movies = []
movies = this.data.movies.concat(newMovies)
this.setData({
movies
})
动态设置导航栏 loading 图标
loading 可以给用户心理上一种等待中,将会获得数据的安心感。
我们无需写代码,直接用 api 即可
wx.showNavigationBarLoading()
wx.hideNavigationBarLoading()
注意在 onload 中调用该 api 是有风险的,官方文档明确说明应在 onReady 页面生命周期之后再操作界面元素。所以最好还是在 onReady 函数中设置 loading 状态
暂无评论