APICloud AVM 多端开发 |外卖 app 开发案例源码教程(上)
AVM 多端开发是 APICloud 定义的一套新的代码编写标准(DSL):基于标准 Web Components 组件化思想,兼容 Vue / React 语法特性,通过一次编码,分别编译为 Android 和 iOSAPP、小程序代码,实现多端开发。
《外卖 app 开发》是一个餐饮商户单商家堂食下单应用,开发者可以通过这个案例体验一套代码编译 Android 和 iOS app+小程序。它的主要功能包括浏览商家主页信息、查看推荐菜品、下单商品、取餐等号等功能。
项目源码位置:https://github.com/apicloudcom/ordering-food
首页 TabBar 结构的处理
为什么需要一个 app.json
配置文件
《外卖 app 开发》项目的首页是由一个可以同级切换窗口组构成的。 在 APP
原生端 上面, 我们可以借助 FrameGroup
来实现这样的切换组。 小程序原生上则是使用 app.json
配置文件来 配置定义 TabBar 的相关属性 。 为了统一两端的差异问题,通过在 weight
根目录下定义一个 app.json
文件,具体字段说明请参考《openTabLayout布局文档》 。 所以,如果只书写原生端 APP
,而不计划支持小程序的话,这个配置文件就是可选的了。
TabBar 页面的组织
在这个配置文件中,可以声明底部栏的标签文案、对应图标的选中和未选中状态以及对应需要跳转的页面路径。 所以需要准备四个主页面。 在 pages
目录准备建立这四个页面。 分别是 “商家主页” main_home
、 “菜单页面” main_menu
、 “购物车页面” main_cart
和 “用户主页” main_user
。 为了兼容小程序目录结构,需要使用同名文件夹对其包裹一层。
商家主页 main_home
的编写
到主页效果图,然后大致分析一下页面结构。源代码在 /widget/pages/main_home/main_home.stml
。 页面主要部分是一个滚动效果,需要使用一个 scroll-view
来做滚动部分的容器。 头部有一个固定头部,并跟随上面提到的 scroll-view
的滚动高度来做透明度反馈。
布局结构使用系统推荐的 flex
布局。有一点需要注意的是, flex
布局的 flex-direction
默认是 column
, 也就是竖着排列的方向,这一点是和传统网页中不一定地方。另外,每一个组件默认会附带 display:flex;
属性。
请求接口数据 (数据处理和请求库封装)
在页面的生命周期 apiready
中,有一个 this.getData()
的方法,就是在请求数据。
这个函数主要使用一个 GET
方法实现的。这个方法来自于:
这个文件中,主要处理了应用的请求、会话和异常处理等逻辑。 相关业务代码可以只是作为参考,具体项目中根据实际的会话认证方式、服务接口模式以及个人偏好等方式去组织。
拿到数据以后,通过 this.data.shopInfo = data
将数据交给到页面的数据域中,以便于接下来的数据绑定显示。
商家头图和主要信息 (数据绑定)
头部主图是不会和 scroll-view
一起滚动的,所以它应该在滚动容器的外部。使用一个 img
图片标签来显示图片。 其数据是来自服务器接口的数据, 使用 avm.js
提供的《数据绑定》 来处理数据。
商家的营业信息也同上,按照接口数据绑定出相应字段,即可显示出来。
拨打电话的动作 (事件绑定)
其中电话的图标点击以后,需要实现拨打电话的效果。为其绑定一个点击事件,叫做 callPhone
,并在 methods
去实现:
推荐菜品和栏目 (v-for 循环和组件)
仔细观察这里的模板和数据,实际上可以分解为 一个主标题
加上 一组菜品
这样的结构来循环。 其中 一组菜品
再使用循环,渲染出单品。
使用循环来展示三个分组数据
每一个循环中包含一个 <goods-list-item />
组件。这个组件来自于自定义组件:
在自定义组件中,完成组件内部的组件样式、数据管理和事件响应等,符合组件化开发思想和提高项目的开发效率和维护性。 在这个组件中,同样的使用了循环来处理每个栏目的单品数据。 每个单品绑定了一个 intoGoodsDetail
事件来实现跳转到商品详情页。
页面头部 header
头部是一个普通的 view
+ text
的结构。为了实现滚动处理透明度,为其绑定一个动态的 style
属性。 动态改变其透明度 opacity
。
而这个 opacity
的取值依赖于 scroll-view
的滚动高度。 scroll-view
的滚动会触发相关数据的变动,所以为其绑定上一个滚动事件 @scroll="onScroll"
和相关处理逻辑 onScroll
。
在 onScroll
中能够拿到相应的滚动高度,并且计算出透明度的最终结果。 同时发现透明度的更改也会伴随着顶部状态栏文本的颜色变化。使用端能力 api.setStatusBarStyle
来进行相应设置。
如此一来,商家主页的相关逻辑的数据处理的差不多了,同时介绍了基础的事件和数据处理等。
商品详情页 (组件通信、全局数据和事件)
页面加载的时候,通过页面传参拿到商品详情数据。另外一个商品的加购数量是存在名为 CART-DATA
的全局数据中,在页面生命周期函数 apiready
中拿到相关数据:
计数器组件 goods_counter
商品详情页使用了两个自定义组件,一个是 goods_counter
,是一个商品计数器。 以后其他页面可能也会使用到,所以将其封装起来。
使用一个动态属性 :count="count"
将刚刚获取到的当前商品的加购数量传入。 在 goods_counter
内部,点击加减按钮触发 countChange
事件。在事件中向父页面传递:
所以在组件调用的时候,绑定一个 onCountChange={this.countChange.bind(this)}
。 这里的 this.countChange
是 goods_detail
的函数,在创建组件的时候作为 props
传递到了子组件中, 在子组件中可以直接执行这个函数,或者是使用 fire
的方式“引燃”这个函数。
加购动作条 goods_action
商品详情页使用了两个自定义组件,另一个是 goods_action
,是一个商品加购动作条。 主体是两个按钮,一个加购,一个结算。
结算就是携带当前单品数据到预付款页面。逻辑很简单,就是携带数据到新页面。
加购稍微复杂一点,不过逻辑依然使用 fire
的方式上抛给一个 addCart
的事件到父页面,因为可能不同的页面的加购后续逻辑不太一样,具体实现就交给父级。 所以视线还是转回到 goods_detail
的 addCart
的实现。
加购后考虑到相关购物车页面和底部小红点的数据。此时如果不考虑小程序的话,也可以直接发送全局广播,自行处理相关逻辑。
版权声明: 本文为 InfoQ 作者【APICloud】的原创文章。
原文链接:【http://xie.infoq.cn/article/b170761590396881014344c70】。文章转载请联系作者。
评论