毕设要求写一个浏览器端,一个APP端,一个微信端,刚开始以为要学三个技术然后写三个客户端,后来知道了uni-app这个神器,一次编写就可以编译生成APP、H5以及各种小程序版本的客户端。然而我比较熟悉的是web的前端开发,而且浏览器用于测试也是唾手可得,所以整个开发过程中用浏览器测试的基本上都很顺利,展现的效果也很好,然而在编译小程序端的时候出了很大的问题,整个页面都扭曲了,经过这两天的查资料与修复,终于得到了浏览器中的效果,正好也记录一下这些坑。
1.不允许id选择器
这个问题是最容易发现的,在h5页面中用id标记标签很常见,然后在css中用#+id来设置标签的style,但是微信小程序中是不能用id选择器的,从警告内容中很容易发现。
从警告中还可以看出,小程序中标签名、属性名选择器都不能用。
2.默认竖排
在H5页面中,元素默认是横排的,但是在小程序中,元素是默认竖排的,因此最好显式的设置元素的横排竖排,这样就不会发生页面错乱了。
.row-arrange{
flex-direction: row; /*横排元素*/
}
3.图片加载不出来
其实这个原因官网的文档上有写,不过我没仔细看
而且H5中用相对路径可以正常加载,但是在小程序中就不行了,所以最好还是用绝对路径吧。
../../../static/xxx.jpg # 相对路径
/static/xxx.jpg # 绝对路径
4.eval函数不可用
之前写H5的时候,总是很习惯的用eval(字符串)来得到数字、JavaScript对象等,但是在微信小程序端这些转换都会报错,因此最好的方式是使用对应的转换API,比如数字可以用parseInt、JSON对象可以用JSON.parse等。
5.getStorage异步
在H5页面中,这样写是可以拿到存储的数据的:
var data;
uni.getStorage({
title : 'xxx',
success : function(res){
data = res.data;
}
})
this.data = data;
但是在小程序中,这段代码就会出错,我猜是小程序中读取存储数据略慢吧,而且我上面的这种写法也不标准,因此严格应该这样写就不会出错:
var vm = this;
uni.getStorage({
title : 'xxx',
success : function(res){
vm.data = res.data;
}
})
6.props的中的值不可修改
props : {
questions : {
type : Array,
default : []
},
},
如上所示,我一开始是直接利用questions中的数据通过v-for来进行动态的页面渲染,用这种方式questions的值可以直接从标签的属性设置,会非常方便,即使后面利用this.questions.push(x)给它增加新元素H5页面也可以更新。但是在微信小程序端就没有反应了,不管怎么修改,它都不能动态的进行渲染,因此我在data中增加了一个ques用来进行渲染的数据来源:
data() {
return {
ques : [],
};
},
props : {
questions : {
type : Array,
default : []
},
},
created : function(){
...
this.ques = this.questions;
},
然后只需要利用ques中的数据进行渲染即可,如果要添加元素,也是通过修改ques来办到,如this.ques.push(x)
7.wx.uploadFile携带字符串参数
上传文件时,按照微信官方的文档,总是不能成功提交表单格式的字符串参数,有一种解决方法是把上传文件和上传字符串分割成两个接口,但由于我的上传文件包含权限验证的token,因此必须在上传文件的同时携带token才行,所以最终用了拼接地址的方法解决了这个问题:
wx.uploadFile({
url: vm.fileurl + '/file/uploadPic?token=' + tokenJson['token'] + '&userId=' + tokenJson['userId'], //图片文件上传接口
filePath: vm.src,
name: 'pic', //
header: {
'Content-Type': 'multipart/form-data',
},
formData: {
method: 'POST' //请求方式
},
success (res){
...
}
})
8.picker的multiSelector mode中选择框出现undefined
展示一下出错的效果图:
可以看到所有的选项都成了undefined。
这里是因为我一开始的数据使用的都是普通数组,每一列都是字符串或数字数组,比如[[1,2,3],[1,2,3,4,5]]这样,在H5页面中这样做没有问题,但是在小程序中就会出现错误,因此这里每一列都必须采用对象数组,例如一个很简单的解决方案:
首先写数据的时候需要用对象数组的方式
data() {
return {
area : [[{'name':'北京市'},{'name':'河北省'}],[{'name':'邢台市'},{'name':'石家庄市'}],[{'name':'不知道县'}]],
areaIndex : [1,0,0],
}
}
然后在标签中用如下的方法:
<picker mode="multiSelector" :value="areaIndex" :range="area" range-key="name" @columnchange="changeColumn" style="width:100%;">
<view class="row-arrange">
<text class="little-font-size">{{area[0][areaIndex[0]].name}}</text>
<text class="little-font-size">{{area[1][areaIndex[1]].name}}</text>
<text class="little-font-size">{{area[2][areaIndex[2]].name}}</text>
</view>
</picker>
注意这里的range-key不能带冒号,而且里面的值应该是对象数组中的key