小程序基础请参考之前的文章: 一个简单的微信小程序DEMO
在既有的某html5移动端项目基础上,考虑到其形态和体量很适合转化为微信小程序,遂花费了不长的时间撸起袖子试试看,并将期间遇到的踩坑心得记录在此
之前的项目中使用express模拟前后端通信数据(mock),对其稍加改造,就可以在保留对原项目的支持的同时,满足小程序的测试了
//小程序中的每次请求
wx.request({
url: `http://127.0.0.1:3201${url}`,
data: assign(
data,
{
_from_weapp: 1, //添加特殊标记,以作区分
code: _globalData['wx_code'],
openid: wx.getStorageSync('openid')
}
),
...
});
//mock中的过滤器
app.all('/api/*', function(req, res, next) { //判断来源是不是小程序
const IS_WEAPP = req.method == 'GET'
? req.query._from_weapp == 1
: req.body._from_weapp == 1;
...
});
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();
});
https://servicewechat.com
和之前的经验相比,小程序中的素材图片需要考虑以下几点
因此,基本的运用原则就是:最小化使用素材图片,并且除了系统 tabBar 等处用到的图标等需要把图片文件打包到发布结构中,其他素材图片尽量 base64 转码后放入 wxss
/*在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;
}
//转码的脚本
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 += '\n\n';
return rst;
}).join('\n'));
由于之前的项目以较合理的方式运用了 rem 尺寸,稍加改造就可以方便的转化到小程序要求的 rpx
/*既有项目中的LESS预处理*/@remUIWidth: 720; /*之前的设计图尺寸*/.px2rem(@px, @name: font-size){
@{name}: unit(@px, px);
@{name}: unit(@px / (@remUIWidth / 20), rem);
}....logout {
.px2rem(130px, margin-left);
}
/*编译结果*/
.logout {
margin-left: 130px;
margin-left: 3.61111111rem;
}
改为小程序的 rpx 格式,并依旧用 Less 预处理:
@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);
}
/*编译结果*/
.logout {
margin-left: 130px;
margin-left: 135rpx;
}
小程序现在并不允许外链,但即使是应用内的跳转,却也分出了好几种不同的方式,即便不爽还是必须了解的:
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 的功能小程序虽然已经出台多时,但在很多方面都在不断改变和完善,es6和css的语法方面,可以通过“开启 ES6 转 ES5 ”和“开启 上传代码时样式文件自动补全”来解决,但一些所谓新API,还是要手动判断处理:
const hide_loading = () => {
if (wx.hideLoading) {
wx.hideLoading()
} else {
wx.hideToast()
}
};
if (wx.reLaunch)
wx.reLaunch({
url: rst.route
})
else
wx.switchTab({
url: rst.route,
})
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 跳转该例因为是不同参数的本页跳转,在旧版客户端中尝试了几种旧有属性值都无法实现,故特殊处理:
<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>
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
小程序当前并不支持原生的“组件”概念,只能用 js / wxml / wxss 中可用的模块化方法变通替代实现
对于较简单的可复用组件,如果没有较复杂的逻辑,只考虑模版和样式即可:
<!-- 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 }}" />
/* tabs.wxss */
.scope {
overflow: hidden;
}
.top-tabs {
...
}/* rank.wxss */
@import './tabs.wxss';
...
小程序提供的组件中并不包含
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;
}
* 原创文章转载请注明出处