小程序基础请参考之前的文章: 一个简单的微信小程序DEMO
在既有的某html5移动端项目基础上,考虑到其形态和体量很适合转化为微信小程序,遂花费了不长的时间撸起袖子试试看,并将期间遇到的踩坑心得记录在此
目录
- 复用的mock
- 素材图片处理
- 样式的转化
- 小程序中几种不同的跳转
- 小失所望的兼容性
- 差强人意的小程序“组件”
- 在小程序中实现表格
1. 复用的mock
之前的项目中使用express模拟前后端通信数据(mock),对其稍加改造,就可以在保留对原项目的支持的同时,满足小程序的测试了
1.1 识别请求来源为小程序
代码语言:javascript复制//小程序中的每次请求
wx.request({
url: `http://127.0.0.1:3201${url}`,
data: assign(
data,
{
_from_weapp: 1, //添加特殊标记,以作区分
code: _globalData['wx_code'],
openid: wx.getStorageSync('openid')
}
),
...
});
代码语言:javascript复制//mock中的过滤器
app.all('/api/*', function(req, res, next) { //判断来源是不是小程序
const IS_WEAPP = req.method == 'GET'
? req.query._from_weapp == 1
: req.body._from_weapp == 1;
...
});
1.2 登录态和权限管理
- 服务器端通过用户唯一标识openid识别用户
- 小程序通过api获得code,传递给服务器换取并缓存openid
- 每次请求都携带openid
- 登出或超时后服务器在响应中返回状态码401触发重新登录
1.3 跨域ajax设置
代码语言:javascript复制app.all('/api/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header("Content-Type", "application/json;charset=utf-8");
next();
});
- 要允许小程序跨域访问,服务器端应做必要的设置
- 最主要的响应头Access-Control-Allow-Origin,在实际测试时不能为通配符 *,应该写为小程序实际发起请求的域名,也就是
https://servicewechat.com
2. 素材图片处理
和之前的经验相比,小程序中的素材图片需要考虑以下几点
- 微信小程序限制总体积,一些资源宜改为远端读取
- 样式表中直接引用的图片要求绝对路径,对于更改域名等调试操作不便
因此,基本的运用原则就是:最小化使用素材图片,并且除了系统 tabBar 等处用到的图标等需要把图片文件打包到发布结构中,其他素材图片尽量 base64 转码后放入 wxss
代码语言:javascript复制/*在wxcc中的引用*/
.figure {
width: 27rpx;
height: 25rpx;
display: inline-block;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAZCAYAAADAHFVeAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1 /AAAABd0RVh0Q3JlYXRpb24gVGltZQAyMDE3LjUuMjKXkY//AAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAAgVJREFUSImtldGRokAQhj te9cQyED22alamAlgyWDZDAxhjeC8CGQjWBKA5YF7381AM8AIvIdpcJxDC8WpskBo/q b buZ4K2yqANgBYRADmTaqMaPG7qOx2N3PvVAKfANJHLpN1CVRT2/F auDiagLVABoTYqAp6AQIDhQ2AitAUOwAtSmTbqG4geBWwr2wB7Ef0BtlKpCwR4HwWT/XgG3sUI0QVgDozau19Y14E1BtqopizqCMgEiMS8AusxsIkIf2mjJv7NsqgzgQB8aKPSWwG91pf 8lclx/U9IH9NgZ2c9zmtTSAfCwKYaqN2WCemPfczbDs8rs9E9MUXlEQi fvQPjsAmT avD4bBewcWBZ1Anxieyzyh68YKMfuYyRJ4MWkcr/RRm3g3I2TnuDtFeAc69AAWGmjMudehm2TAzBrNWK97DTOpr48/AYs6Jn2zoTZ4UwYB7TWRs1dja/yb6fxXyPfWOFCYhZYR4dtrGhsJLEk1svdWWV3VPgBNMAf7NzsYkUjwr7y/GJlQyv0YkNOE6czkKMR91Y2tEIv9lKLdAlerczJus3u1goT7L4FQDAI5gH3QKqNqq7EtsCZXHqL9TIbDBORCLvZM6w5cm1U7sXMOVU0a0Ew8DX2iK3k12b w2lvnuW4B9JYL6v22ZthHjjBfppCrPUb7Bc/b93ojqt/8akRua fVJwAAAAASUVORK5CYII=');
background-position: 0 50%;
background-repeat: no-repeat;
background-size: contain;
margin-right: 12rpx;
}
代码语言:javascript复制//转码的脚本
const base64Img = require('base64-img');
const imgs = Array.from(process.argv).slice(2);console.log(imgs.map(imgPath=>{
let rst = imgPath 'n-------------------n';
rst = base64Img.base64Sync(imgPath);
rst = 'nn';
return rst;
}).join('n'));
3. 样式的转化
由于之前的项目以较合理的方式运用了 rem 尺寸,稍加改造就可以方便的转化到小程序要求的 rpx
代码语言:javascript复制/*既有项目中的LESS预处理*/@remUIWidth: 720; /*之前的设计图尺寸*/.px2rem(@px, @name: font-size){
@{name}: unit(@px, px);
@{name}: unit(@px / (@remUIWidth / 20), rem);
}....logout {
.px2rem(130px, margin-left);
}
代码语言:javascript复制/*编译结果*/
.logout {
margin-left: 130px;
margin-left: 3.61111111rem;
}
改为小程序的 rpx 格式,并依旧用 Less 预处理:
代码语言:javascript复制@WEAPP-WIDTH: 750;
@ui-width: 720;.px2rpx(@px, @name: font-size){
@{name}: unit(@px, px);
@{name}: unit( floor(@px * @WEAPP-WIDTH / @ui-width), rpx);
}....logout {
.px2rpx(130px, margin-left);
}
代码语言:javascript复制/*编译结果*/
.logout {
margin-left: 130px;
margin-left: 135rpx;
}
4. 小程序中几种不同的跳转
小程序现在并不允许外链,但即使是应用内的跳转,却也分出了好几种不同的方式,即便不爽还是必须了解的:
wx.navigateTo()
保留当前页面,跳转到应用内的某个非 tabBar 的页面wx.redirectTo()
关闭当前页面,跳转到应用内的某个非 tabBar 的页面wx.switchTab()
跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面wx.navigateBack()
关闭当前页面,返回上一页面或多级页面wx.reLaunch()
关闭所有页面,打开到应用内的某个页面
<navigator />
组件中有一个 open-type
属性,分别对应以上类型:
navigate
对应 wx.navigateTo 的功能redirect
对应 wx.redirectTo 的功能switchTab
对应 wx.switchTab 的功能reLaunch
对应 wx.reLaunch 的功能navigateBack
对应 wx.navigateBack 的功能
5. 小失所望的兼容性
小程序虽然已经出台多时,但在很多方面都在不断改变和完善,es6和css的语法方面,可以通过“开启 ES6 转 ES5 ”和“开启 上传代码时样式文件自动补全”来解决,但一些所谓新API,还是要手动判断处理:
旧版本微信客户端不支持 showLoading() / hideLoading()
代码语言:javascript复制const hide_loading = () => {
if (wx.hideLoading) {
wx.hideLoading()
} else {
wx.hideToast()
}
};
旧版本微信客户端不支持 reLaunch,分情况用不同方法代替
代码语言:javascript复制if (wx.reLaunch)
wx.reLaunch({
url: rst.route
})
else
wx.switchTab({
url: rst.route,
})
某些ios客户端中,程序甫一启动时,立即调用 reLaunch() 会报错,需要延时处理
代码语言:javascript复制if (res.statusCode == 401) {
setTimeout(function() {
if (wx.reLaunch)
wx.reLaunch({
url: '/pages/login/login'
});
else
wx.redirectTo({
url: '/pages/login/login'
})
}, 500);
return;
}
兼容处理 <navigator />
组件的 reLaunch 跳转
该例因为是不同参数的本页跳转,在旧版客户端中尝试了几种旧有属性值都无法实现,故特殊处理:
代码语言:javascript复制<navigator wx:if="{{ tabs.current !== tab.key }}"
url="{{ tabs.links[idx] }}"
data-url="{{ tabs.links[idx] }}"
open-type="{{ tabs.openType }}"
catchtap="onTabClick">{{ tab.label }}</navigator>
代码语言:javascript复制const openType = wx.reLaunch ? 'reLaunch' : 'navigate';...//在 onLoad(opts) 中
this.setData({
tabs: {
openType,
current: opts.key,
tabs: result.tabs,
links: result.tabs.map(
tab =>`/pages/path?time=${opts.time}&key=${tab.key}`
)
},
...
});...onTabClick(evt) {
if (openType === 'reLaunch') return;
const {url} = evt.currentTarget.dataset;
const [m, time, key] = url.match(/time=(.*?)&key=(.*?)$/);
this.onLoad({time, key});
}
其他一般的兼容处理方法见官方文档: https://mp.weixin.qq.com/debug/wxadoc/dev/framework/compatibility.html
6. 差强人意的小程序“组件”
小程序当前并不支持原生的“组件”概念,只能用 js / wxml / wxss 中可用的模块化方法变通替代实现
对于较简单的可复用组件,如果没有较复杂的逻辑,只考虑模版和样式即可:
代码语言:javascript复制<!-- tabs.wxml -->
<template name="tabs">
<view class="top-tabs">
<block wx:for="{{ tabs.tabs }}" wx:for-item="tab" wx:for-index="idx" wx:key="key">
...
</block>
</view>
</template><!-- rank.wxml -->
<import src="tabs.wxml" />
...
<template is="tabs" data="{{ tabs }}" />
代码语言:javascript复制/* tabs.wxss */
.scope {
overflow: hidden;
}
.top-tabs {
...
}/* rank.wxss */
@import './tabs.wxss';
...
7. 在小程序中实现表格
代码语言:javascript复制小程序提供的组件中并不包含
table
、thead
、tr
等,但是用css属性和<view />
组件旧可以完美模拟一个文首展示的表格
/*table by <view>*/
.table {
border-collapse:collapse;
border-spacing:0;
width:100%;
display: table;
}
.table .thead {
display: table-header-group;
}
.table .tbody {
display: table-row-group;
}
.table .tr {
display: table-row;
}
.table .th,
.table .td {
display: table-cell;
}
* 原创文章转载请注明出处