从App Inventor到微信小程序

微信小程序是近一两个月来国内移动应用领域的热点话题之一,从九月下旬发送内测邀请开始,一直到最近的开放公测,每一步推进都在开发者圈里引起了极大的反响,各类技术分析文章和开发教程也纷纷出笼、营造声势。毕竟微信具有庞大的用户群体和高效的传播渠道,每一个新平台的推出,对开发者和应用产品而言,都是不容轻易错失的良好发展机会。问题是,对同处于移动应用开发领域的App Inventor开发者而言,这又意味着什么?能不能说,这也是一次由单一平台向更广大应用领域跨越的良好机会?其中的门槛有多高?要付出努力的有多大?凭借App Inventor所建立的开发思想、经验和能力,有多少能应用到微信小程序的开发实践中?

实际上,App Inventor尽管定位于Android应用开发,但就语言本身而言却是中立的,而且由于采用了主流的组件化开发方式,对底层实现技术的细节进行了良好封装,应该说对具体平台的依赖性和绑定性并不是很强,更何况现在市面流行的各类移动平台和产品在结构和功能方面也日渐趋同,所以从理论上讲,我们用App Inventor所建立的一套成熟开发模式和思维,应该可以很容易地平滑移植其他类似的新平台上去,甚至相比其他新手,转换的成本还要更低一些。唯一需要跨越的门槛,可能是由可视编程语言向文本编程语言的转换,不仅仅是语法,应该还包括一些具体的编程习惯、思想和方法等。

具体到微信小程序的开发本身,如果仔细研读一下公众平台所提供的技术规范和样例代码,不难发现,它和App Inventor在应用结构、组件类型和开发思路方面有着诸多的对应性和相似性,这为我们切入这个领域的开发又增加了极大的成功可能。

首先,和App Inventor一样,微信小程序也采用了由组件-->容器-->应用的分层架构形式。具体说,在App Inventor中,承载应用的主体叫项目(Project),项目中所包含的个体叫屏幕(Form或Screen),然后屏幕再由各种类型的组件构成。所谓App Inventor应用开发,本质上就是,通过设计,用各式各样的组件来构建一个个的屏幕,最后把所有屏幕在统一打包为项目。映射到微信小程序的结构里,项目的对应实体叫做App(应用),屏幕的对应实体叫做Page(页面),Page同样由组件构成,只是这里的组件(界面组件)实际是对应于App Inventor中的可视组件,而另外的API组件(接口组件)则对应于App Inventor中的非可视组件。

再进一步,我们来看系统结构所对应的设计文件,微信小程序的页面实际包括页面结构、页面样式、应用逻辑(js)和页面配置(json)等四个组成部分,分别对应于wxml、wxss、js和json文件,其中最最要的是页面结构和应用逻辑两个部分。从App Inventor的视角看,其实这就是设计视图中的组件列表、组件属性和编程视图中逻辑代码,分别对应于scm和bky两个文件。其作用也是相同的,就是 分别用于定义对用户可见和可交互的前端用户界面,以及具体实现应用功能和控制前端页面变化的后端应用逻辑。

最后从组件的类型和分组看,除了一些与自身业务功能强相关的部分外,整体上二者之间都有很明显的对应性,或者,至少从概念上很容易让人理解。比如微信小程序中的View相当于App Inventor中的布局组件,Text相当于标签组件等等。差别之处在于,微信小程序中的"非可视组件"API只能用于应用逻辑部分,而不能在用户界面设计文件中出现,而在App Inventor中,两类组件都必须在设计视图中被添加和设定,当然,这是与App Inventor中屏幕对象的特殊性有关。

以上我们对App Inventor和微信小程序在整体结构、类型等方面的对应性和相似性进行了初步的分析,希望熟悉App Inventor开发的读者对微信小程序的开发能形成一个整体的认识。接下来我们要通过一个大家都熟知的HelloPurr入门应用,来对照和展示一下微信小程序的具体开发过程。

HelloPurr的基本形式和功能很简单,就是应用启动后,会在界面上显示一段文字“宠物小猫”和一张小猫的图片,当用户点击这张图片时,会听到“喵”的一声猫叫。

在App Inventor中,我们一般会先创建项目实体,输入项目的名称及相关信息,包括在后面出现的设计视图中设定应用的名称、版本以及状态栏和标题等,最后这些信息都会被写入一个名为project.properties的项目配置文件。微信小程序也有类似的设定过程,但相关的文件一共有三个,即应用实体设定文件app.js、应用配置设定文件app.json和应用样式设定文件app.wxss,其中前两个文件是必不可少的(如果缺少了app.js,整个应用就不能被加载,而如果没有app.json,则不能加载应用中所包含的页面)。创建的具体方式是,在存放应用文件的根目录下,手工创建app.js和app.json,由于我们所创建的应用功能上比较简单,所以我们暂时让第一个文件为空,然后在第二个文件中,加入以下内容:

{  "pages":[    "index"  ],  "window":{    "backgroundTextStyle":"light",    "navigationBarBackgroundColor": "#fff",    "navigationBarTitleText": "你好,猫咪",    "navigationBarTextStyle":"black"  } }

值得注意的是文件中数据的书写形式,这是在JavaScript和微信小程序中经常使用的一类形式,无论是应用的配置、页面的定义,还是在设置API组件的调用参数时都会采用。实际对于App Inventor开发者来说,对这种数据形式应该并不陌生,它其实就是我们在App Inventor中经常使用的的键值对列表,但在这里,不仅格式上有些微的差异,而且意义上也有了本质的不同。在JavaScript中,键值对是对象的数据表示形式,其中除可以使用数字、文本以及逻辑、列表等基本类型的数值外,还可以把函数、对象等作为键值。在App Inventor中虽然也可以把组件实例对象用作列表和键值对的值,但整体上,不能将形成的实体当一个自定义的对象来使用,这也是需要大家熟理解和适应的重要之处,当然熟悉JavaScript开发的读者另当别论。

回到上面这段代码,其中最关键的部分有两个,一个是pages健对应的列表(姑且采用App Inventor中的说法吧),应用中所包含的所有页面必须列入其中(只包含文件完整路径,不包含后缀),另一个是window健对应的键值列表,其中定义了整个应用标题栏上的一些特性,比如定义标题内容的navigationBarTitleText等。

在完成应用实体的创建和设定后,就着手进行具体的应用开发设计了,和App Inventor一样,主要包括用户界面设计和应用逻辑设计两部分。我们知道,App Inventor的流程一般是,首先要在设计视图中设计用户界面,根据功能需要将所需的组件添加进来,然后在属性面板中分别设定这些组件的属性,最后在编程视图中实现应用功能,通过代码读写组件的属性状态状态或调用组件的功能。为了便于大家理解和对照,我们仍采用App Inventor的流程和习惯来设计微信小程序版的HelloPurr。

第一步,设计页面结构。我们要创建一个后缀为wxml的文件,文件名为上面app.json中所列入的页面名,比如index.wxml,然后在其中分别写入Text和Button组件对应的代码,前面我们说过,它们的作用相当于App Inventor中标签和按钮。如果需要排列和对齐的话,还可以在其外面加入一层具有布局作用的View组件,整体看起来应该是下面这个样子:

<view>  <text>文本1<text>  <button>按钮1</button> </view>

第二步,设定组件属性。为界面中的组件设定属性,按照App Inventor的设计方式,最重要的属性应该是组件的id和宽度、高度、显示文本以及背景图片或颜色等,按HelloPurr的设计需求,分别设置如下:

<view id="layout1" style="display:flex;flex-direction:column;height:100vh;align-items:center;justify-content:center;">  <text id="label" style="color:white;background-color:blue;font-size:50rpx;margin-bottom:10rpx">宠物小猫<text>  <button id="button1" style="width:294rpx;height:270rpx;background-image:url(kitty.png) no-repeat;"></button> </view>

因篇幅的缘故,具体的设置方法和特性说明也不再赘述,请大家自行查阅相关的技术资料和手册,熟悉HTML和CSS开发的读者应该很容易读懂。其中需要注意的一点是,为了和App Invnetor中的背景图片属性相对应,我们这里通过background-image样式来设置按钮的背景图片,尽管在目前文件结构下不会出问题,也能通过测试,但实际是违反了CSS样式不能加载本地图片的技术限定,一旦将图片文件移入某个目录(如assets)就会出现引用出错。所以,我们这里对其进行稍加调整。

<view id="layout1" style="display:flex;flex-direction:column;height:100vh;align-items:center;justify-content:center;">  <text id="label" style="color:white;background-color:blue;font-size:50rpx;margin-bottom:10rpx">宠物小猫<text>  <view>    <image src="kitty.png" mode="aspectFit"></image>  </view> </view>

其实就是利用一个可以实现交互功能的布局组件(View)将图片包裹在内,这点是和App Inventor稍有差别的地方,App Inventor中的布局组件虽然也能嵌套,但只能当做容器,而不能侦测用户的交互行为。

第三步,编写应用逻辑。这是微信小程序和App Inventor差别最大的地方,在App Inventor中,我们都是直接在代码中调用组件对象的属性和方法,因为就同一个屏幕(Form)来说,它们都是在同一个域里,所有组件实体对于屏幕都是可见的。而在微信小程序中,用户界面和应用逻辑是处于不同的域中,相互之间不能直接交流,只能通过应用来做中介,所以需要采用不同于App Inventor的方式和组件实体进行信息交互。

具体做法是,首先在页面对象中建立一个能够响应用户点击行为的方法,这其实和我们在App Invenotr中编写当什么什么被点击时的逻辑没什么两样,只是这时不需要去关心具体的组件是什么,而是把注意力集中在要实现的功能上。在方法的实现代码中,我们使用了一个非可视的API接口组件wx,通过调用其playBackgroundAudio方法实现播放声音的功能。

var index = {  playMeow: function(res) {        wx.playBackgroundAudio({            dataUrl: 'http://www.17coding.net/download/1/meow.mp3',            title: ' ',            coverImgUrl: ' '        }) } Page(index)

注意,我们这里采用上面说过的键值对形式来定义页面的特性,但必须将其带入Page函数进行注册才能使这样的特性生效,其实就是通知微信小程序的引擎应该如何对应前端用户界面所发生的变化。另外在playBackgroundAudio参数中,之所以音频文件采用的是网络资源,是因为小程序对于多媒体素材只支持网络形式,这有可能会在应用体验上造成一定的影响,具体的优化、解决办法留给大家自己去思考,这里不再进一步分析、讨论了。

接下来的问题是,如何把写好的功能绑定到界面的组件上去?很简单,就是为wxml中的View组件增加一个属性bindtap,让其属性值等于上面已经写好的playMeow方法,修改后的代码如下:

<view id="layout1" style="display:flex;flex-direction:column;height:100vh;align-items:center;justify-content:center;">  <text id="label" style="color:white;background-color:blue;font-size:50rpx;margin-bottom:10rpx">宠物小猫<text>  <view>    <image src="kitty.png" mode="aspectFit"></image>  </view> </view>

实际这种绑定方式解决了我们在App Inventor中经常会遇到的一个棘手问题,就是组件实体和组件事件的处理逻辑之间耦合性太强,即便是多个组件调用同样的功能,也必须在逻辑代码里一个一个地写入多个对应的事件方法。而采用微信小程序的方式,我们只需在需要绑定逻辑的组件里设定好相关属性即可,完全不用改动后端的逻辑,可以极大提高开发的效率以及代码的质量。

至此,我们通过简单的三个步骤,已经完成了HelloPurr的全部构建工作,最后形成的项目文件夹应该如下图所示:

将项目上传到微信小程序平台,并用在微信中预览后,效果如下:

尽管因网络加载的缘故,使得实际的使用效果有些卡,但从功能上还是基本完成了最初设定的目标。

总起来看,从App Inventor到微信小程序的转换门槛应该还是较低的。实际从应用开发的发展历程看,从桌面时代开始,组件化就是一种高效的主流开发方式,到了今天,随着AngularJS、ReactJS和Vue等框架的出现,互联网的开发也进入到了模块化和组件化的时代。在这种模式下,组件和框架在应用开发中的作用要高于基本语言要素的作用,对于新手,经常面临的问题是,一门语言的语法、规则很容易掌握,但要想全面把握组件框架、设计思路和模式却很难。如何能从一门低门槛但功能全面的语言和工具出发,低成本地快速掌握和熟练使用相关领域的一整套基本开发方法和设计思路,就变得至关重要,也许,这就是今天我们应该学习App Inventor的意义所在吧。

(0)

相关推荐