前言
最近在开发小程序项目,将项目中遇到的问题和要点记录下来,方便以后查阅。
字体
全局字体
项目中使用了 vant-weapp,有赞开源的小程序组件库。
为保证在不同设备上提供最佳的视觉体验,且与组件库风格统一,可在 app.wxss 中设置以下全局字体。
page {
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica,
Segoe UI, Arial, Roboto, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft Yahei',
sans-serif;
}
字号单位
字号单位用 px,不同分辨率设备上字体大小保持一致,取值尽量是偶数。
可以将常用的字号写成 css 变量,方便使用。
page {
--font-size-xs: 10px;
--font-size-sm: 12px;
--font-size-md: 14px;
--font-size-lg: 16px;
--font-size-xl: 18px;
--font-size-xxl: 24px;
}
view {
font-size: var(--font-size-md);
}
图片资源
项目中经常会使用图片、SVG 等文件,而这些文件占据项目体积很大的比重。因小程序包体积限制,需要对图片文件进行压缩处理。
WXS 工具方法
WXS 是小程序的一套脚本语言。语法跟 JavaScript 类似,但其中有一些坑。比如不能遍历对象。没有 Object 对象,不能使用 for ... in ...
。小程序社区里也有关于这个的吐槽。
只能通过正则的方式来实现对象的遍历方法:
// object.wxs
var REGEXP = getRegExp('{|}|"', 'g');
function keys (obj) {
return JSON.stringify(obj)
.replace(REGEXP, '')
.split(',')
.map(function(item) {
return item.split(':')[0]
})
}
function values (obj) {
return JSON.stringify(obj)
.replace(REGEXP, '')
.split(',')
.map(function(item) {
return item.split(':')[1]
})
}
module.exports = {
keys: keys,
values: values,
}
iPhoneX 适配
屏幕上边框,右边框,下边框,左边框安全距离:
safe-area-inset-top
safe-area-inset-right
safe-area-inset-bottom
safe-area-inset-left
使用:
iOS 11
padding-top: constant(safe-area-inset-top);
padding-right: constant(safe-area-inset-right);
padding-bottom: constant(safe-area-inset-bottom);
padding-left: constant(safe-area-inset-left);
iOS 11.2 beta 及其后
padding-top: env(safe-area-inset-top);
padding-right: env(safe-area-inset-right);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
兼容性写法:
padding-top: constant(safe-area-inset-top);
padding-top: env(safe-area-inset-top);
参考文档:苹果官方文档
iOS 中 Promise 对象不存在 finally 方法
在开发者工具中没有这个问题,只在 iOS 真机中存在。不知小程序官方是否修复了此 bug。
在 app.js 中添加如下代码:
if (!Promise.prototype.finally) {
Promise.prototype.finally = function (callback) {
this.then(res => {
callback && callback(res)
}, error => {
callback && callback(error)
})
}
}
引入路径
在小程序中 import ... from ...
和 require
不支持绝对路径。只能使用相对路径引入,如果目录过深就会写成 ../../../../util.js
,不够直观优雅。
可以通过以下方式优化引入:
// app.js 中
App({
require (path) {
return require(`${path}`)
}
})
在其他 page 和组件中,就可以统一相对于根路径引入。
const app = getApp()
const { formatTime } = app.require('/utils/util')
SKU 商品规格
SKU 是指物理上不可分割的最小存货单元
开发的是电商类型项目,SKU 商品规格选择功能是必不可少的,也是项目中比较复杂的功能。将功能封装为组件,具体的代码查看该地址。

笛卡尔积应用
SKU 商品规格选择是 C 端的功能,其中还涉及到如何生成商品 SKU 数据。也就是笛卡尔积的应用。
如上图所示,通过“颜色”和“尺寸”2个销售属性来生成商品的 SKU,就需要对属性的值做笛卡尔积,其中核心代码如下:
/**
* @desc 多数组求笛卡尔积
* @param { Array } array [['粉色', '黄色', '蓝色'], ['大', '小']]
* @return { Array } ['粉色', '大'], ['粉色', '小'], ['黄色', '大'], ['黄色', '小'], ['蓝色', '大'], ['蓝色', '小']
*/
function cartesianProduct (array) {
return array.reduce(function (a, b) {
return a.map(function (x) {
return b.map(function (y) {
return x.concat(y)
})
}).reduce(function (a, b) { return a.concat(b) }, [])
}, [[]])
}
总结
这些都是最近项目中记录下来的,欢迎大家交流,以后开发中碰到了其他问题也会持续更新的。