Menu
小程序资讯
小程序资讯
lypeer:一名Android开发者的微信小程序填坑之路《上》
时间:2016-10-17 11:05:00

前言

首先要声明的是,我是一名 Android 开发者,之前基本没有前端开发经验,甚至连 JS ,HTML 都是为了开发小程序现学的一些皮毛——所以文章中所提到的一些点也许在资深前端开发者看来只是小case,但是站在一个 Android 开发者的角度来看确实是大坑。

前面就不说太多东西了,文章的末尾再谈谈我对小程序的一些看法——这篇文章主要是谈谈在开发小程序的过程中遇到的一些坑。

PS:推荐一下我写的一个微信小程序版的Gank客户端:wechat-weapp-gank

正文

1,获取小程序开发工具并正确安装?

最近在一些地方看到很多人在入小程序坑的第一步就出现了很多的问题,其实很早之前(22号)关于怎样搞定小程序的开发工具就已经有比较好的资料了,大家可以直接去看一下然后照着做,基本上就没啥问题:获取小程序开发工具并正确安装的教程

2,直接在微信开发工具上写代码?

目前来讲,我们只能在微信的开发工具上编译小程序的代码,但是这并不意味着我们必须要在那个开发工具上写小程序的代码——用过那个开发工具的人就会知道,那个开发工具并没有多好用,代码提示挺弱鸡的,而且没有自动保存是硬伤。

那么怎么办呢?我们完全可以在别的工具里面写代码然后在小程序的开发工具里面编译。我试过 sublime 和 webstorm , 都是可以在上面开发的,但是最后还是发现 ws 更好用。我就不讲 sublime 怎么用了,大家只需要直接在里面打开项目文件夹然后点右下角选择当前的语言就可以了。接下来着重讲一讲如何在 ws 里面编写小程序代码。

首先选择小程序的目录在 ws 里面打开,这是很简单的。但是这个时候打开里面的文件之后你会发现,除了 js 代码它能认出来之外,其他的代码他都并不能够认出来——主要是 .wxml 和 .wxss 文件。为什么呢?因为虽然 .wxml 和 .html 文件很像,.wxss 文件和 .css 文件很像,但是编译器并不知道!这样一来,我们就无法在这两种文件里面享受 ws 强大的代码提示功能了——我们能接受这种事么?果断不能!那么接下来我们应该怎么办呢?告诉编译器,.wxml 格式的其实是 HTML 文件,.wxss 格式的其实是 CSS 文件。

上图把做这件事的流程讲的很详细了,.wxss 文件的转化同理。这样做了之后,编辑器就会知道他们的真实面目,然后就可以有棒棒的代码提示了(但是请注意,有写微信自己写的东西编辑器不仅没有代码提示反而会报错,不管他就好了)!接下来就可以直接 ws 一个桌面小程序开发工具一个桌面,在 ws 里面写了代码直接划过去点编译了。

3,跳转page的时候怎么传递数据?

小程序给我们开放了很好的接口来进行页面之间的跳转:

但是在这个地方微信官方对于这一个接口并没有太多的描述,只是简简单单的给了我们一行代码:wx.navigateTo({url: "test ? id = 1"}); ,其实这里这样写是有些难以理解的——test 是个什么鬼 ? id 是个什么鬼?中间那个问号是个什么鬼?这都是些什么鬼?

反正我看到的时候是一头雾水的。不过还好,经过一些摸索,终于知道了他们是啥。首先,代码里的 test 代表要跳转到的 page 的url 地址。比如:

那么代码就应该是:

wx.navigateTo({url: "/pages/specific/specific"});
  • 1
  • 1

聪明的人可能已经发现了,上面的代码没有了示例代码里面 ? id = 1 的部分,怎么回事,是我写错了么?并不是。这一部分其实是跳转 page 时用来传值的关键方法,并不必需,但很有用。

? 是一个分隔符一样的东西,它的后面就是所有要传到目标 page 的值。而这些值是通过键值对来一一对应的,每个键值对之间用 & 隔开。但是要注意的是,似乎这种方式传值只能传 String 过去,不是 String 类型的值传过去之后也会被转化为 String 。*比如,我传了个 array 和 json 过去:

var arrayData = ["firstData" , "secondData"];
var jsonData = {first: "firstData" , second: "secondData"};
wx.navigateTo({url: "/pages/specific/specific ? data: " + arrayData + "&json=" + jsonData});

结果目标page里接受到的是:

//目标page的onLoad方法
onLoad: function (options) {
        //结果是:firstData , secondData
        console.log(options.data);
        //结果是:f
        console.log(options.data[0]);
        //结果是:[object Object]
        console.log(options.json);
        //结果是:undefined
        console.log(options.data.first);

        //很显然,被转化了  
}

上面其实也演示了如何在目标 page 里面接收传过来的数据,直接在 onLoad() 里面的 options 取就可以了。

另外,其实更多的时候我们的需求并不是直接传一个固定的参数到目标 page 里面去,而是根据用户的一些操作传递不同的值到目标 page 里面去,这个时候该怎么办呢?要知道,我们是没有办法获得组件的(这点太坑了,没有 window 和 document)。这个时候,我们可以通过 dataset 来通过绑定组件数据达到目的。什么?你不知道 dataset 是什么东西?

多读书,多看报,多看文档少睡觉。

4,某些图片无法加载?

这个坑真的是深坑,可能很久很久都不会遇到,但是一旦遇到真的很蛋疼。

我拿来练手的项目是 Gank.io 的客户端,而 Gank 网站上的图片都是寄放在新浪图床上的,默认的存储的 url 是http://ww{1 || 2 || 3 || 4}.xxxxx.xxxxx.jpg然后在小程序里死活都加载不出来这些图片!!!

我一开始不知道到底是小程序的 <image> 标签的问题还是图片的问题,就找了很多地方的图片来做测试,包括 CSDN 上的,简书上的,github 图床上的,结果是这些图片都可以正常显示——甚至新浪微博上的,一些人的头像,都可以显示!后来我发现,只要 URL 是 ww+数字 开头的图片,都不能正常的显示!这也太坑了。。。后来我就在思考怎么解决这个问题——要么改变 标签,他自身肯定是有问题的,可能对某些来源的图片不太友好;要么改变图片,让它去适应这个 标签。这两方面要改其实都挺难的,但是显然第一种方式基本上是不可能的,就只能在第二种方式上去下功夫。

最后经过不断地尝试,我总结了很多规律,最后通过把图片的 URL 由 ww+数字变成 ws+数字 解决了这个问题,让图片得以显示在小程序上。比如:

本来的URL:
http://ww1.sinaimg.cn/large/610dc034jw1f87z2n2taej20u011h11h.jpg
变换之后的URL:
http://ws1.sinaimg.cn/large/610dc034jw1f87z2n2taej20u011h11h.jpg

不要问我为什么这样改了就可以显示了,因为我也不知道。。。太神奇了。。。

5,this.setData() 显示没这个方法?

首先想要说的是,作为一个 Android 开发者,我非常不适应小程序的数据与控件绑定的方式。在 Android 开发的时候,我们是可以直接获得控件然后对控件做数据绑定的工作的,而在小程序里,我并不能够直接获得控件的对象,所有的数据绑定与动态修改只能通过维护 Page 里面的 data{} 以及调用setData() 方法来进行,我不好评判这两种方式的优劣,只能说真的很不习惯。

但是有些和我一样以前没怎么接触过前端开发的朋友在做这个的时候就有可能会踩坑了——setData() 是 Page 这个层级上的方法,并不是在任何地方调用 this.setData() 方法都可以顺利的得到我们预期的结果的。比方说:

Page({
    onLoad: function (options) {
        wx.request({
            url: Constant.GET_URL,
            success: function (res) {
                this.setData({...});
            }
        });
    },
});

我在 wx.request() 的回调接口里面 success() 里面写 this.setData({...}),就不能完成预期操作,程序会报错说没有 setData() 这个方法,因为这个时候 this 获取到的已经并不是 Page 了,上下文已经发生了变化,那么当前层级没有 setData() 方法就很正常了。那么怎么解决这个问题呢?像这样:

Page({
    onLoad: function (options) {
        that = this;
        wx.request({
            url: Constant.GET_URL,
            success: function (res) {
                that.setData({...})
            }
        });
    },
});

var that;

和一开始的区别在于多了一个全局变量 that,并且在 onLoad() 方法里面对它进行了赋值,使它等于 this。这样的话,我们就可以在这个 Page 的任何地方调用 that.setData() 来动态的改变控件的属性了。

结语

本来是还有一些问题要谈一谈的,但是写到这里篇幅已经挺长的了,就干脆把其他的放到下一篇里面算了。剩下的问题还有:

  • 后台接收数据需要表单?小程序并不能很方便的获得数据的表单,甚至 <form>标签获得的数据也不是。
  • 解析 HTML 块?没有document,没有window,解析它简直是一种折磨。
  • <form/> 里面无法获取 <picker/> 的取值?明明文档里有说在 <form/> 里面是可以支持 <picker/> 的,结果你会发现死活无法获得他的值。
  • 要实现多层列表?有的时候也许需要在一个列表项的每一项下面又有一个子列表,在小程序里怎么做?
  • 如何方便愉快的实现类似 Java 里面的静态变量的效果?没有一个专门的类存放 static final 的值供其他地方使用感觉全身都不自在。

接下来我想谈一下我对小程序的看法。

  • 第一点,不管小程序能不能在未来的时间里在移动端大放异彩,学习它,掌握它,都是没有任何坏处的。
  • 第二点,就目前的版本而言,小程序的表现让我有些失望——实在是太过封闭。开发小程序就感觉像是在微信给我们划定的一个小圈子里兜兜转转,在圈里也许我们能得到很良好的开发体验,但是一步都出去不得。
  • 第三点,在性能与便捷之间,最终往往会是便捷取胜。
  • 第三点,能用 js 开发的,最终都会用 js 开发。

多谢各位看官看到这,顺便去点个star吧:wechat-weapp-gank