汇聚支付宝、微信小程序多年开发经验,包括css样式隔离、小程序modal弹窗滚动穿透等,解决了很多这种大家都没解决的问题,以及对这两种常开发的小程序做了一些对比。
1、标签语法替换
关于点击事件,在微信小程序中text没有点击事件,记得替换成view
以下是支付宝vs微信的标签对比
a: -> wx:
onTap -> bindtap
catchTap -> capture-catch:tap
my. -> wx.
2、for循环处理
for循环中一定要用引号包裹起来
<!-- 支付宝 -->
<view a:for={{expressLogs}}/>
<!-- 微信一定要引号 -->
<view wx:for="{{expressLogs}}"/>
微信添加key
<!-- 支付宝 -->
<view a:key="{{item.name}}/>
<!-- 对应微信这里写法是这样的 -->
<view wx:key="name"/>
<!-- 也可以固定写法直接index -->
<view wx:key="index"/>
微信不支持反引号`
<!-- 支付宝 -->
<view slot="{{`title_${index+1}`}}"/>
<!-- 微信 -->
<view slot="title_{{index+1}}"/>
3、自定义js脚本替换
首先js脚本导包替换如下
<import-sjs from="../../utils/filter.sjs" name="tofix" />
<wxs src="../../utils/filter.wxs" module="tofix" />
然后微信小程序xml中不支持js的方法,例如substr、indexof,需要用到微信小程序自定义的js脚本。以substr示例
正常:item.activityTag.substr(0,2)
微信小程序:tofix.substr(item.activityTag,0,2)
4、props替换
1、有用到props传参的要定义好properties,微信小程序只会接受properties参数,不定义好会报错。
2、微信小程序中没有this.props概念,代码中所有的this.props都应该删除,且用this.data、this.triggerEvent替换。
// 支付宝
props: {
collectList: null,
},
//微信
properties: {
// 写法1
collectList: {
type: Array,
value: [],
},
// 写法2
collectList: Array,
},
5、生命周期替换
// 支付宝小程序(组件生命周期)
didMount(){},
// 微信小程序(组件生命周期)
ready(){},
6、导包替换
微信小程序不支持根路径
import common from "/utils/common";//支付宝支持根路径
import common from "../../utils/common";//微信只能用相对路径
7、授权组件button属性替换
授权组件button要替换open-type、onGetAuthorize两个属性,对比如下
<!-- 支付宝 -->
open-type="getAuthorize" onGetAuthorize="login"
<!-- 微信 -->
open-type="getPhoneNumber" bindgetphonenumber="login"
完整示例如下
<!-- 支付宝小程序 -->
<button class="auth-btn" type="primary" open-type="getAuthorize" onGetAuthorize="login" onError="getPhoneErr"
scope='phoneNumber'>{{isLogining?'正在登录中':'点击授权登录'}}</button>
<!-- 微信小程序 -->
<button class="auth-btn" type="primary" open-type="getPhoneNumber" bindgetphonenumber="login" onError="getPhoneErr"
scope='phoneNumber'>{{isLogining?'正在登录中':'点击授权登录'}}</button>
8、登录方法替换
微信登录调用loginValidate()接口,不调用login(),完整示例如下
// 支付宝小程序
loginFirst(callback, failedCallback) {
if (this.data.isLogin) {
callback();
return;
}
common.showLoading("正在登录中...");
if (this.data.isLogining) {
return;
}
this.setData({ isLogining: true });
app
.login()
.then(res => {
common.hideLoading();
this.setData({ isLogining: false });
if (res) {
this.setData({ userInfo: res, isLogin: true }, () => {
callback();
});
} else {
// 授权失败直接进入
failedCallback && failedCallback();
}
})
.catch(err => {
common.hideLoading();
this.setData({ isLogining: false });
failedCallback && failedCallback();
});
},
// 微信小程序
loginFirst(callback, failedCallback) {
if (this.data.isLogin) {
callback();
return;
}
common.showLoading("正在登录中...");
if (this.data.isLogining) {
return;
}
this.setData({
isLogining: true
});
app
.loginValidate()
.then(res => {
common.hideLoading();
this.setData({
isLogining: false
});
if (res) {
this.setData({
userInfo: res,
isLogin: true
}, () => {
callback();
});
} else {
// 授权失败直接进入
failedCallback && failedCallback();
}
})
.catch(err => {
common.hideLoading();
this.setData({
isLogining: false
});
failedCallback && failedCallback();
});
},
9、父组件调用子组件
微信小程序中没有ref,只有id
ref="orderCRef" 替换成id="dailog-modal"
this.orderCRef.showModal(); 替换成
this.selectComponent("#dailog-modal").showModal();
10、子组件调用父组件
1、绑定方法 onRefleshCallback换成bind:onRefleshCallback
2、样式itemStyle从”小驼峰“换成”小写字母加分割线“
3、回调方法从this.props换成this.triggerEvent(同时从properties中移除onRefleshCallback方法)
4、避免出现回调不生效,xml中方法命令必须on打头
// 父页面使用组件
<goods-item collectList="{{specialGoodsList}}" onRefleshCallback="onCollectedBySpuid" itemStyle="backgroundColor:white;width:48.5%;borderRadius:1rpx;marginBottom:20rpx;borderRadius:16rpx;" />
// 组件调用父页面方法
this.props.onRefleshCallback();
// 父页面使用组件
<goods-item collectList="{{specialGoodsList}}" bind:onRefleshCallback="onCollectedBySpuid" itemStyle="background-color:white;width:48.5%;border-radius:1rpx;margin-bottom:20rpx;border-radius:16rpx;" />
// 组件调用父页面方法
this.triggerEvent('onRefleshCallback');
11、view绑定参数替换
在给view绑定参数时,如果参数存在大写字母
<view data-orderId="{{item.orderBaseVO.orderId}}"/>
在微信小程序中需要手动改成小写才能接收
toDetail(e) {
// 支付宝
const orderId = e.currentTarget.dataset.orderId;
// 微信
const orderId = e.currentTarget.dataset.orderid;
}
推荐使用解构赋值,优势:对应字段会清晰点 (冒号后面为:字段别名)
toDetail(e) {
const {
orderid: orderId
} = e.currentTarget.dataset;
}
12、text字符串换行
支付宝小程序下支持在标签下直接写文案
比如以下示例
1、支付宝小程序展示”¥测试1000.00元“,展示ok的
2、微信小程序展示”¥
测试1000.00元“,就会换行
<text>
¥
<text class="fm">测试1000.00元</text>
</text>
解决方法:如果设计到字符串水平排列的,在微信小程序中我们对文案尽量都用标签包裹
<text>
<text>¥</text>
<text class="fm">测试1000.00元</text>
</text>
13、scroll-view组件不支持flex布局
微信小程序scroll-view组件存在坑
1、宽度全屏,需要设置css的宽度如下
width: fit-content;
2、默认不支持flex,比如设置横向排列无效(flex-direction:row;),需要添加enable-flex="true"属性
<!-- 无效 -->
<scroll-view scroll-x="{{true}}">
<!-- 有效 -->
<scroll-view scroll-x="{{true}}" enable-flex="true">
3、不支持padding
例如设置右边距(不支持 )
padding-right: 20rpx;
改成如下方式即可
<scroll-view scroll-x="{{true}}" enable-flex="true">
<view style="width: 20rpx;"/>
</scroll-view>
14、消息订阅
注意:微信订阅入参是tmplIds
// 支付宝
my.requestSubscribeMessage({
entityIds: common.couponRemindIds,
complete: res => {
},
})
// 微信
wx.requestSubscribeMessage({
tmplIds: common.couponRemindIds,
complete: res => {
},
})
15、弹窗
微信提供了代码调用的简单对话框,使用起来方便点。不过ui效果需要跟设计沟通
wx.showModal({
title: '温馨提示',
content: '请先允许订阅权限',
confirmText: "同意",
cancelText: "拒绝",
success: function (res) {
if (res.confirm) {
wx.openSetting();
}
}
});
支付宝
my.confirm({
title: "温馨提示",
content: "请先允许订阅权限",
confirmButtonText: "同意",
cancelButtonText: "拒绝",
success: function(res) {
if (res.confirm) {
my.openSetting();
}
}
});
16、view动态设置背景图片(background-image)
支付宝写法
<view style="{{`backgroundImage: url(${tofix.dealImageUrl(iversion,Imgs.mingxiPopBar)});`}}"/>
在微信中,需要用括号包裹计算部分,即url({{计算部分}})的写法。
<view style="background-image: url({{tofix.dealImageUrl(iversion,Imgs.mingxiPopBar)}});">
17、输入框组件
支付宝输入框的绑定事件是onInput,到微信需要改成bindinput
<!-- 支付宝 -->
<input onInput="onExpressInput" />
<textarea onInput="onExpressInput" />
<!-- 微信 -->
<input bindinput="onExpressInput" />
<input bindinput="onExpressInput" />
18、联系客服组件使用
- json中导包
"usingComponents": {
"cell": "plugin://contactPlugin/cell"
},
- xml布局
正方形的用styleType1,长方形的用styleType2
<cell class="my-cell" plugid='479e29dbdc7c024d123ccdb295e06524' styleType="1" />
- css样式
.my-cell {
position: absolute;
z-index: 2;
opacity: 0;
}
子布局如有溢出的,使用css样式控制
overflow: hidden;
19、小程序modal弹窗滚动穿透
支付宝小程序、微信小程序默认都存在滚动穿透的问题,如下图所示
1、支付宝小程序解决滚动穿透
使用touch-action控制,注意在支付宝开发工具的模拟器上不生效
<!-- 注意:touch-action在模拟器上不生效 -->
<view style="touch-action: {{dialogShow?'none':'auto'}};">
</view>
2、微信小程序解决滚动穿透
使用页面属性配置节点page-meta,只要包裹在页面标签的最外层即可
解释:页面属性配置节点:用于指定页面的一些属性、监听页面事件。只能是页面内的第一个节点。
<!-- page-meta 只能是页面内的第一个节点(禁止滚动) -->
<page-meta page-style="{{ dialogShow ? 'overflow: hidden;' : '' }}" />
<view>
<!-- 这是你正常的页面 -->
</view>
20、动态传递style、className
动态样式传入到组件。
common-select-popup.axml
<view class="view-container {{className}}" style="{{style}}">
</view>
common-select-popup.js
props: {
style: '',
className: '',//支付宝小程序写法
//className: {//微信小程序写法
// type: String,
// value: '',
},
},
你的页面.axml
<common-select-popup style="margin-top:10rpx;" className="express-log-step"/>
21、匿名插槽slot、具名插槽
匿名插槽
common-select-popup.axml
<view>
<slot>
</view>
你的页面.axml
<common-select-popup>
<text>asdf</text>
</common-select-popup>
具名插槽
common-select-popup.axml
<view>
<slot name="title1" />
<slot name="title2" />
</view>
你的页面.axml
<common-select-popup>
<view slot="{{`title_${index+1}`}}">
</view>
</common-select-popup>
22、button去掉边框
支付宝小程序(给button添加属性)
border: none;
opacity: 0;
微信小程序 (页面css底部设置)
button::after {
border: none;
}
23、样式隔离
如果遇到小程序文件之间样式互相影响,可以配置这个
微信(配置在.js文件中)
Component({
options:{
styleIsolation: "isolated" // 启用样式隔离
// styleIsolation: "apply-shared" // 页面影响组件,组件不影响页面
// styleIsolation: "shared" // 不隔离,相互影响
},
})
支付宝(配置在.json文件中)
{
"component": true,
"styleIsolation": "apply-shared"
}
24、列表元素撑满布局的坑
布局常用撑满高度,一般用以下几种。
/* type 1 */
flex:1;
/* type 2 */
height: 100vh;
/* type 3 */
height: 100%;
/* type 4 */
display:position/fixed;
top:0;
bottom:0;
但是常用的办法会导致android被挤扁,如下图
height: 100%;或者flex:1;会导致页面撑不开
处理办法:套两层,注意height:100%要放里面一层
<view style="height:100vh;">
<view style="height:100%;">
<slot />
</view>
</view>
25、参数乱码
在url参数上有乱码时,需要套上
// 编码
encodeURIComponent(JSON.stringify(你的json对象))
// 解码
JSON.parse(decodeURIComponent("你的json字符串、或者普通字符串"));
1、对于支付宝,在路由层面上对所有参数接收都做了解码,虽有一般用不上decodeURIComponent
2、对于微信则没有,所以一定要decodeURIComponent,同时放心解码,用decodeURIComponent多次包裹也没事。
26、微信image标签有外间距
微信小程序如下图所示,会漏出一部分黄色背景,按理说不应该有这个,且支付宝小程序无此BUG。
分析:微信小程序对image有一个默认样式 屏幕的宽为375 图片默认的宽320 图片的宽没有平铺整个屏幕的宽度 默认的display 为inline-block 所有剩下就是给右边距了你把图片设置有对齐边距就给左边了css 的样式为题。
解决:添加image布局方式为flex即可
display: flex;
27、微信小程序wxs报错Unexpected token .
、Unexpected token >
在微信小程序中
filter.wxs
文件中报错
function getReuseImageList(list, isGoods = true) {
return list.filter(item => item.imageType === 2);
}
相对支付宝小程序,微信存在更多的缺陷和BUG。
这里就是因为微信小程序wxs不支持ES6语法,去掉箭头函数(=>)、拓展操作符(…)即可
28、多行text前面加上icon,文本的第二行与icon对齐
<!-- 支付宝 -->
<view class="vip-top" style="{{`backgroundImage: url(${tofix.dealImageUrl(iversion,Imgs.vipNewTopBg)});`}}"/>
<!-- 微信 -->
<view class="vip-top" style="background-image: url('{{tofix.dealImageUrl(iversion,Imgs.vipNewTopBg)}}');"/>
- 给子组件加属性
display: inline-block;
- 富文本
<rich-text nodes="{{nodes}}"></rich-text>
nodes: [
{
name: 'div',
attrs: {
class: 'my-class',
style: 'display: flex; align-items: center;'
},
children: [
{
name: 'img',
attrs: {
src: 'https://mmm-jyj.oss-cn-hangzhou.aliyuncs.com/iDiamond-mini/reuse/icon_tui.png',
style: 'width: 20px; height: 20px; margin-right: 5px;'
}
},
{
type: 'text',
text: '这是一段带图片的文本'
}
]
},
{
type: 'text',
text: '这是另一段普通文本'
}
]