manlili blog

小程序开发中遇到的问题

今天公司的主项目保养小程序上线了,可以搜索小程序全名“4S店汽车维修保养”体验下,本人这次项目中主要负责样式和业务逻辑的实现,趁着有空写写开发中遇到的问题,都是小问题,重在积累.

样式问题

样式单位

小程序提供了两种单位:
(1)rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在iPhone6上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
(2)rem(root em): 规定屏幕宽度为20rem;1rem = (750/20)rpx 。
根据我们公司的设计稿(以苹果6为标准设计),我选择了rpx,我们的设计稿宽度是750px,直接可以用设计稿上的1px = 1rpx
(这里必须提的就是微信0.5px的实现,直接用1rpx,这样就能做出很细的线,但是很多安卓低端机上面还是将0.5px当做1px渲染)

可使用的标签

下面是项目中总结出来的项目中总结出来部分标签
(1)支持的标签: view text span image ul li picker footer header table ::after ::before
(2)不支持的标签: div img del

引入icon

小程序提供了一些基本的icon,但是远远满足不了我们项目需求,为了不引入图片增加额外的服务器请求,我的解决方式是采取base64的方式,先到阿里巴巴矢量图标库[http://iconfont.cn/]生成自己的字体图标,并下载下来,找到ttf格式文件然后去[https://transfonter.org/],把字体文件转化成base64格式,按下图进行
图然后将生成的代码拷贝进全局global.css就可以实现引入icon,注意引入icon的方式用伪元素实现。
需要注意的是tabbar不支持icon,只支持图片和文字。

引入自定义组件

(1)import方式
import可以在该文件中使用目标文件定义的template,而且有作用域的概念,即只会 import 目标文件中定义的 template,而不会 import 目标文件 import 的 template。
(2)include方式
include可以将目标文件除了template的整个代码引入,相当于是拷贝到include位置
详见[https://mp.weixin.qq.com/debug/wxadoc/dev/framework/view/wxml/import.html]
由于项目需要引入自定义的组件,比如提示表单验证,比如网速慢正在加载中,或者其他什么提示类的组件,所以我这里采取了比较简单的include方式

btn

小程序的button里面文字的垂直居中实现的方式是line-height,也就是说遇见下面情况button中文字就没法像平时那样垂直居中
图
因为是上图中button高度不一样,没有办法定义一个固定的line-height,解决的方式如下(不是唯一的):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.father {
position:absolute;
top:0;
right:0;
z-index:1;
height:100%;
width:115rpx;
background-color:#fa5a4d;
color:#fff;
font-size:30rpx;
}
.child {
position:absolute;
top:50%;
-webkit-transform:translateY(-50%);
transform:translateY(-50%);
}

就是将父元素的高度定义为整个框的高度,然后对里面的child进行垂直居中。

float布局bug

可能是微信小程序的bug,我在写日历页如下图
图
上图中每一天用到了float布局排列,其他组件也用到了float布局,大面积使用float布局,在安卓手机上没有问题,但是在苹果手机上却是乱的,找不到错误的原因,就暂时用display:inline-block解决

样式引入图片

样式里面引入的图片不能为本地图片,需要是https格式,比如

1
2
3
4
5
6
7
8
9
.bi-sex {
width: 90rpx;
height: 90rpx;
background: url(https://img06.lechebangstatic.com/webapp/book/book291481adbf.png) no-repeat center center;
-webkit-background-size: 180rpx 180rpx;
background-size: 180rpx 180rpx;
display: inline-block;
margin-left: 10rpx;
}

引入本地图片,本地可以调试可以看见,一旦发布到测试环境则会发现图片不见了,所以需要替换图片的地址。

table布局渲染

微信小程序里面会将table布局渲染成wx-table wx-td等等,这点要分清,要不然调样式很容易找不到对应的类名

固定底部与固定顶部布局

虽说微信提供了tabbar,但是他是针对页面切换,当一个页面需要切换不同的条件比如
图
上图中顶部需要固定的bar不用像H5里面做各种兼容,直接用fixed布局就可以,不用考虑input聚焦时fixed布局的问题,微信已经帮我们做好了,很方便

样式技巧

小程序是运行在微信提供的 webview 上面,也就是说他们封装了一系列的属性,比如page ,button ,如果想改变微信固有标签的样式,只需要直接写个一样的类名加样式就可以了,小程序还是很人性化的,将开发者的样式权限提高。
开发完20多个页面的样式整体的感受如下(只是本人愚见):
(1)有点讨厌微信自定义标签,比如view,image其实完全可以用div,img代替,当然这也是它提高竞争力的表现
(2)微信文字与文字,数字,图片的对齐方式做的很好,以前H5项目中需要微调很多小细节,在小程序里面正常布局都差不多已经自动对齐了,不需要多担心。
(3)微信的1rpx做的很惊喜,因为大胆的实现了0.5px,先不说兼容性,至少0.5px使H5页面更像原生的app

业务逻辑问题

点击事件

具体如下图
图
上图中如果想点击查看使用规则详情而不是选择使用这张券的话,就需要使用阻止事件冒泡。
小程序的事件分为冒泡事件和非冒泡事件:
(1)冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递
(2)非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。
bindtap事件绑定不会阻止冒泡事件向上冒泡,catchtap事件绑定可以阻止冒泡事件向上冒泡。
根据这个页面的的需求,选择使用catchtap。

wx:key

小程序我们列表渲染的时候会用到wx:for,它有个属性wx:key:
即当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。
不得不说这个属性很好用,当我们需要按不同条件排列列表的时候,列表可以不用重新渲染,只是调换下位置,避免了用户的等待时间。

setData

页面渲染完以后再去改数据,直接修改this.data无效,无法改变页面的状态,还会造成数据不一致,如果使用setData就可以解决了,格式如下

1
2
3
this.setData({
text: 'changed data'
})

事件传值

html与js传值时,可以用自定义属性(data-*)实现html触发的事件时,会发送给事件处理函数
例如视图代码如下

1
2
3
<view class="bd-noorder-tips" data-id="{{id}}" bindtap="ruleAction">
使用规则
</view>

逻辑层代码如下

1
2
3
ruleAction (e) {
console.log(e.currentTarget.dataset.id)
}

页面跳转

(1)navigaterTo可以再url后面还拼参数,这样可以把需要的参数带到别的页面,
(2)navigaterBack是无法往回带参数的然后有的时候需要去别的页面插值的时候需要往上一级页面传参,这里我是用的setStorage的方式写入缓存中,这样在上一级页面的onShow中可以再进行塞值处理

wx.navigateTo无法打开页面

(1)wx.navigateTo保留当前页面,跳转到应用内的某个页面
(2)wx.navigateTo关闭当前页面,跳转到应用内的某个页面
wx.navigateTo无法打开页面,微信小程序规定一个应用同时只能打开5个页面,当已经打开了5个页面之后,wx.navigateTo不能正常打开新页面。请避免多层级的交互方式,或者使用wx.redirectTo

添加类名

js添加类名的方法我只找到了一种,感觉使用三元表达式添加类名不怎么美观,但是找不到第二种方法了,使用方法如下

1
<view class="bd-coupon-price {{item.strategyKind === 1 ? 'bd-coupon-yellow-bg' : ''}} {{item.strategyKind === 2 ? 'bd-coupon-blue-bg' : ''}}"></view>

输入法中键盘完成按钮触发

在input输入文字的时候,习惯性用输入法键盘中的“完成”按钮,这时候会自动提交表单,小程序提供了这个方法bindconfirm
点击完成按钮时触发,event.detail = {value: value}

使用local跨页面传值

小程序里面不能使用session传值,所以项目里面使用local传值。

技巧性问题

注册页面

每一个新写的页面必须在app.json的pages里面

1
2
3
4
5
6
7
"pages":[
"pages/index/index",
"pages/detail/detail"
],

注意第一个页面路径是页面渲染起始页面,所以开发时为了方便开发可以在app.json里面将正在开发的页面置顶,

将开发页面设为初始渲染页面

方法一:
app.json的pages里面将开发页面配置为第一个

方法二:
小程序开发编辑器右侧->编译->设置启动页面 *必填->写入pages/开发页面名字,但是弊端就是页面的title仍旧是app.json的pages配置第一个页面的title,但是不影响开发。

创建新页面注意

注意创建*.json的时候需要写点代码,空着的json文件会报错

请我喝杯果汁吧!