03-微信小程序踩坑

小程序踩坑

01 cover-view的坑

1.不支持边框样式

比如我要给一个cover-view设置底部边框,我会在下面再添加一个cover-view,给第二个cover-view设置宽度百分之百,高度为1个像素,说白了就是模拟边框

2 滚动问题

tip: 基础库 1.9.90 起 cover-view 支持 overflow-y: scroll,但不支持动态更新 overflow

暂不支持 overflow-x: scroll

3 控制显示

使用 hidden 代替 wx:if

自定义组件嵌套 cover-view 时,自定义组件的 slot 及其父节点暂不支持通过 wx:if 控制显隐,否则会导致 cover-view 不显示

04 绑定事件

1
<button bindtap='toFixInfoPage' data-NO='{{NO}}>Click Me</button>
1
console.log(event.currentTarget.dataset.no);

在绑定事件处理函数的时候,也就是在wxml页面中,data-设置变量的时候是不分大小写的,但是在js里event的dataset就全部转换成了小写,我们在JS页面也只能用小写才能用它!!!

> 传过来的值都是字符串,需注意!!

05 set-Data key值动态设置

这个不算小程序的坑,一个注意点,加上[]中括号:

1
2
3
4
5
6
7
8
const arr=['showProvince','showCity','showArea'];
arr.forEach(item=>{
if(item===type){
this.setData({[type]:true})
}else{
this.setData({[item]:false})
}
})

另外一个例子:

1
2
3
var index=event.currentTarget.dataset.index;
var flag=!this.data.categories[index].active;
this.setData({['categories['+index+'].active']:flag});

06 函数防抖的问题

函数防抖这里引用underscoredebounce

this 绑定不需要更改

例子:

1
2
3
4
getCode:debounce(function(event){
console.log(this);
console.log('提交事件');
},5000,true),

07 input 绑定事件

由于小程序input组件没有提供双向绑定的功能,需要简单加上绑定事件监听

wxml部分

1
2
3
4
5
6
7
8
<input 
bindblur="handleInput" // 防止用户手写获取不到input值
bindinput="handleInput" // 绑定事件
data-inputkey="phone" // 通过inputkey标记
value="{{phone}}"
type="number"
class="yx-input"
placeholder="请输入您的手机号" />

js部分

第一种方案:(只适用单向绑定情况)

1
2
3
4
5
6
/**
* input 绑定事件
*/
handleInput(event){
this.setData({[event.currentTarget.dataset.inputkey]:event.detail. value})
}

第一种方案存在input和textarea在输入内容时,如果在bindinput事件时,通过调用setData保存输入的内容,光标就会自动跑到最后去,这也是个大坑。

第二种方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* input 绑定事件
*/
handleInput(event){
var keyName=event.currentTarget.dataset.inputkey;
var arr=keyName.split(".");
var obj={}
if(arr.length==1){
this.data[keyName]=event.detail.value;
}else{
for(var i=0;i<arr.length;i++){
if(i==0){
obj=this.data[arr[i]]
}else if(i==arr.length-1){
obj[arr[i]]=event.detail.value;
}else{
obj=obj[arr[i]]
}
}
}
}

08 async/await 引入

注意: 小程序于20190508更新了微信开发者工具,增强编译功能已经支持 async ,不再需要引入 regenerator-runtime.js

经过微信开发者工具的不断升级,它的“ES6转ES5”的功能也渐渐有了加强,所以要用async/await的话,只需要引入regenerator runtime就可以了。

需要熟悉async api,特别是报错的处理上!
需要熟悉async api,特别是报错的处理上!!
需要熟悉async api,特别是报错的处理上!!!

regenerator-runtime.js 放到 libs 目录下,在页面引入

1
import regeneratorRuntime from "../../libs/regenerator-runtime"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 注意:这里用了resolve返回布尔值出去,所以在上面不需要 catch promise
* @returns {Promise [boolean]}
*/
verify(){
return new Promise((resolve,reject)=>{
if(this.data.phone===''){
wx.showToast({
title: '请输入手机号码', //提示的内容,
icon: 'none', //图标,
duration: 2000, //延迟时间,
mask: true, //显示透明蒙层,防止触摸穿透,
});
resolve(false);
}
if(!/1[0-9]{10}/.test(this.data.phone)){
wx.showToast({
title: '请输入正确的手机号码', //提示的内容,
icon: 'none', //图标,
duration: 2000, //延迟时间,
mask: true, //显示透明蒙层,防止触摸穿透,
});
resolve(false);
}
resolve(true);
})
},

注意:data数据的获取用 this.data.xx 获取

09 微信小程序里Promise不支持finally

引入 promise-finally.js,放在libs目录下

1
import '../../libs/promise-finally'
1
2
3
4
5
6
7
Promise.prototype.finally = function (callback) {
let P = this.constructor;
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
);
};

10 wxss不能设置本地背景图片

wxss 中的本地资源图片无法通过 WXSS 获取,可以使用网络图片,或者 base64,或者使用标签。请参考文档:https://developers.weixin.qq.com/miniprogram/dev/qa.html#%E6%9C%AC%E5%9C%B0%E8%B5%84%E6%BA%90%E6%97%A0%E6%B3%95%E9%80%9A%E8%BF%87-wxss-%E8%8E%B7%E5%8F%96

采用 image 标签 + 绝对定位

1
2
3
4
5
6
7
8
9
10
.image-section{
position: relative;
}
.image__bg{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
1
2
3
4
5
6
7
8
9
10
11
<view class="dots__item image-section">
<image
class="image__bg"
src="/img/index-bg.png">
</image>
<view class="image__bg">
<view class="dots__name">xxx维修点</view>
<view class="dots__distance">454米</view>
<view class="dots__neast">距离最近</view>
</view>
</view>

11 关于小程序 scroll-view 左右横向滑动没有效果(无法滑动)问题

参考链接

  1. scroll-view 中的需要滑动的元素不可以用 float 浮动;
  2. scroll-view 中的包裹需要滑动的元素的大盒子用 display:flex;是没有作用的;

  3. scroll-view 中的需要滑动的元素要用 dislay:inline-block; 进行元素的横向编排;

  4. 包裹 scroll-view 的大盒子有明确的宽和加上样式–>overflow:hidden;white-space:nowrap;

12 关于小程序UI组件库

这里引用了部分有赞的小程序组件库 vant-weapp

13 textarea使用注意点

13.1 小程序textarea遮挡键盘

设置cursor-spacing, 文档属性说明:

指定光标与键盘的距离,单位px或rpx,默认为px。取 textarea 距离底部的距离和 cursor-spacing 指定的距离的最小值作为光标与键盘的距离

13.2 获取textarea的值

input和textarea都有一个共同的问题,用户使用手写输入法时,bindinput无法获取到用户输入的内容。

解决办法:

再添加一个bindblur事件,可以获取到手写输入法的内容。

参考文章

1
2
3
4
5
6
7
8
9
10
11
<textarea 
bindblur="handleInput"
bindinput="handleInput"
bindconfirm="handleInput"
data-inputkey="installForm.describe"
cursor-spacing="80"
class="textarea-info"
placeholder="请输入服务描述"
name=""
id="">
</textarea>
当键盘输入时,触发 input 事件,event.detail = {value, cursor},bindinput 处理函数的返回值并不会反映到 textarea 上

13.3 textatea在actionsheet隐藏时刻还显示字体

在actionsheet隐藏时刻,通过动态修改 textarea class 解决

1
{{showActionSheet?'':'hide'}}

1
2
3
.hide{
display: none!important;
}
1
2
3
4
5
6
<textarea
cursor-spacing="80"
class="textarea-info {{showActionSheet?'':'hide'}}"
style="background:#fff;"
placeholder="请输入详细地址,如小区、楼座、门牌号等">
</textarea>

14 微信小程序使用wxparse问题:

文档地址

使用wxparse报错template12 not found请看 github issue

14.1 显示图片的相对路径问题

修改 html2json.js
1
2
3
4
5
6
7
8
9
10
11
12
13
//对img添加额外数据
if (node.tag === 'img') {
node.imgIndex = results.images.length;
var imgUrl = “http://www.baidu.com(这块换成你的域名地址前缀就可以了)”+node.attr.src;
if (imgUrl[0] == '') {
imgUrl.splice(0, 1);
}
imgUrl = wxDiscode.urlToHttpUrl(imgUrl, __placeImgeUrlHttps);
node.attr.src = imgUrl;
node.from = bindName;
results.images.push(node);
results.imageUrls.push(imgUrl);
}

14.2 console.dir在真机报错

修改 html2json.js

就是把 console.dir 注释掉,或者用 console.log 代替就好了啊。。这就是一个 log 日志,在功能上没啥用

15. 如何promise微信小程序api

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//util.js
import Promise from './bluebird.min';
export const wxPromise = function(fn) {
return function (obj = {}) {
return new Promise((resolve, reject) => {
obj.success = function(res) {
resolve(res);
}
obj.fail = function(err) {
reject(err);
}
fn(obj)
})
}
}

16. 微信小程序不支持加载本地ttf字体文件

https://transfonter.org/

通过将ttf文件转成base64

17. wx:if hidden 切换自定义组件的坑

含有自定义组件的三个(及其以上?)组件,按照特定顺序(自定义组件位于首位?)排列,并使用 wx:if wx:elif wx:else 条件动态切换组件的渲染,会报错:Error: Expect START descriptor with depth 2 but get another

解决的办法也很简单,把wx:elif或者wx:else或者hidden全部改成wx:if就可以了。

18. 小程序骨架屏实践

具体操作请看 https://github.com/jayZOU/skeleton

19. eslint校验

eslint配置参考AlloyTeam出品

安装:

1
npm install --save-dev eslint babel-eslint eslint-config-alloy

在你的项目根目录下创建 .eslintrc.js,并将以下内容复制到文件中:

1
2
3
4
5
6
7
8
9
10
11
12
{
"extends": ["eslint-config-alloy"],
// 注意这是全局变量,
// 当访问当前源文件内未定义的变量时,no-undef 规则将发出警告
// 所以需要定义这些额外的全局变量
"globals": {
"App": false
},
"rules": {
"indent": ["error", 2]
}
}

创建.eslintignore

1
2
3
build/*.js
config/*.js
src/assets

VSCode 中使用: 安装eslint插件,在「文件 => 首选项 => 设置」

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"eslint.autoFixOnSave": true,
"eslint.validate": [
"javascript",
"javascriptreact",
"html",
{
"language": "vue",
"autoFix": true
},
{
"language": "typescript",
"autoFix": true
},
{
"language": "typescriptreact",
"autoFix": true
}
]
}