本节教程将介绍如何用DeviceOne简单而高效的完成一个新闻页面。
- 导入项目
- 数据模板分离MVVM模型
- 自定义事件
- 展示新闻
- 九宫格展示
将要学习的demo效果图如下所示
1. 导入完整项目
本节示例demo请参考下载地址,可以导入到设计器中学习。
为了方便大家理解页面结构,请参考下图
图中红框所示的上面部分是SegmentView组件,和下面的BottomBar共同组成页面公共部分,而蓝框中是一个SlideView组件,可以左右滑动切换页面且跟SegmentView联动,页面个数则是取决于数据条数,如数据有四条就有四个页面;绿框所示是ListView组件,在本教程中是SlideView的模板,而ListView又可以绑定不同模板来展现不同页面;而黄框所示是跟上节教程中相同的直接引用一个UI页面。总而言之,这里的页面层级关系是SlideView的模板中嵌套了一个ListView,而ListView的模板又是其他不同页面。
2. 数据模板分离DeviceOne
的数据绑定是采用了MVVM模式的,实现了页面和数据分离,数据通过绑定在不同模板上控制了页面的显示。DeviceOne
提供了两个数据绑定组件,都是MM类型组件,一个是ListData,它本质上是一个可变数组(支持JSON array),可以增删改查数据;另外一个是HashData,它本质上是一个可变key-value键值对,也可以增删改查。
这里我们给SegmentView定义一个数据源jsonTabs,
再把这个数据源赋值给数据绑定组件ListData,定义SegmentView的数据模型module。
因为数据绑定组件可以绑定不同的数据源,而一个数据源只能被一个数据绑定组件绑定,是一对多的关系,所以当我们想把相同的数据源作为SlideView的数据模型module时需要复制一份数据源。
定义好数据模型module,我们再来定义ViewModel也就是模板视图。先给SegmentView定义一个模板视图UI页面newsTypeTabTemplate.ui,修改根ALayout的id为do_ALayout_root,里面拖拽一个Label,修改id为do_Label_title,调整Label的位置和大小。
然后我们在newsTypeTabTemplate.ui.js里把Label的text和tag属性通过UI组件
通用的setMapping方法跟数据模型module联系起来,定义映射关系,这样ViewModule模板视图就完成了。(其中name和selected是jsonTabs数据源中的key)
现在只需要修改SegmentView的template属性,将属性值指向我们刚刚定义的newsTypeTabTemplate.ui的url,View和ViewModule就联系起来了。
最后我们要将数据模型module和它们都建立起联系,只需要用SegmentView添加绑定了数据模型module的ListData组件即可。
更多关于数据绑定的介绍,详见数据绑定
3. 自定义事件
为了让更真实的模拟新闻类App的使用习惯,我们处理一下选择不同的SegmentView时底下的SlideView页面也跟着切换的效果,即让SegmentView和SlideView联动起来。这个步骤非常简单,只需要在SegmentView的indexChanged事件中将当前SegmentView所处cell的index赋值给SlideView的cell,即可完成。
我们想要在SlideView切换不同的cell的同时页面数据也跟着切换,这就需要在SlideView的indexChanged事件里做大量操作,为了优化代码结构,这里就将切换数据的操作全部放在自定义事件selectOneTab中完成,只在触发indexChanged事件的回调中同时触发该自定义事件,这样我们在订阅selectOneTab事件时所作代码也都会被执行了。
订阅selectOneTab事件,在其中做更新数据的操作
需要特殊注意的是,自定义事件的订阅和触发可以不在同一个页面的脚本环境中完成,只需要保证自定义事件的触发在订阅之后即可。
更多关于自定义事件的使用,详见自定义事件。
这里为了更好的体验效果,让SlideView能无限滑动并且加载速度更快,只需要简单的设置两个属性即可。其一就是将SlideView的looping属性设置为true,实现无限滑动;其二就是设置isAllCache属性为true,在浏览上一页时预缓存下个页面。
4. 展示新闻
新闻展示页面的数据是通过Http组件请求的后台数据,在手势向下pull或向上push滑动页面时刷新请求,接下来详细说下这个步骤如何实现。
展示新闻
用上面同样的方法,我们先处理一下SlideView的数据和模板,不同的是这里SlideView的模板里嵌套了一个ListView组件,所以我们先处理ListView组件。ListView的数据是从后台通过http请求获取的,所以在添加了ListView的页面newsIndexSlideTemplate.ui对应的newsIndexSlideTemplate.ui.js脚本环境中去请求数据,并在Http的请求成功事件中将数据绑定给一个ListData组件,再让ListView去绑定该数据,同时复位pull或push出来的头部。(需要注意的是,这里直接将请求到的数据绑定给ListView组件,所以需要前后台沟通好数据格式,在后台保存时也是用JSON Array。)
因为ListView是支持多模版的,这里我们给ListView组件绑定两个模板,一个用于展示新闻列表newsRowTemplate0.ui,一个用于展示轮播图片newsRowTemplate1.ui。这两个模板也同样在模板页的根节点上调用setMapping方法定义好数据映射关系,这样数据与模板就结合起来了,在ListView上就能显示我们从后台请求到的数据了。
这里提一个小的处理,因为我们不确定要展示的数据到底有多少个字节,全部展示要占用多大的空间,所以我们设置ListView的模板页中要展示数据的Label的高度为-1,表示自动高度,并且将maxLines属性设置为2,表示最多只显示两行,这样就能控制每个cell显示数据的空间都是固定高度的,数据能整齐排列。
另外一个小处理就是让图片显示的速度更快,因为所有图片都是网络图片,显示之前都会先去请求,这样在网络环境不稳定时可能会导致图片显示框先出现默认图片(设置defaultImage)再显示真正要显示的图片。这里只需要简单的设置ImageView的cacheType为temporary,表示第一次加载图片时就缓存到本地,以后每次打开这个ImageView都会先读缓存的本地图片,然后再读服务器的网络图片,这样就能优化ImageView的加载速度,从而提高体验。
刷新新闻
想要在ListView页面上向下pull和向上push操作中获取新的数据并重新显示在模板中,首先要设置ListView的isFooterVisible和isHeaderVisible属性为true,这样上下拉的时候使头部和尾部可见,再分别在ListView的pull和push事件中去重新请求数据,并且在http请求的success事件中调用ListView的rebound方法让头部或尾部复位。
5. 九宫格展示
最后,我们说一下第三张效果图中点击“+”号会弹出一个快速选择新闻类型的UI界面如何实现。
首先画出需要弹出的UI页面newsTypeGrids.ui,也如之前教程中处理弹出Picker页面一样,在该页面中只放一个GridView组件,其他地方设置成灰色半透明效果。再设置GridView的模板页newsTypeGridTemplate.ui,同样定义好数据映射,将之前给SegmentView定义的数据源也复制一份让GridView绑定上,最后只需要在“+”号的touch事件中让newsTypeGrids.ui显示出来即可。