首页 > 代码库 > WeX5学习笔记

WeX5学习笔记

目录

WeX5学习笔记... 1

1.轻松看透WeX5产品能力和技术... 1

2.WeX5可以怎么玩?... 3

一、纯本地App. 3

二、关联一个网站,希望默认就打开某页... 4

三、UI设计器... 4

四、打包神器... 4

五、标准玩法... 4

3.WeX5 App与服务端交互原理... 4

4.Account示例程序... 5

5.Takeout示例程序... 7

5.1Index.w.. 7

5.2mapActivity.w.. 13

问题... 13

6.页面间交互视频... 15

6.1 页面打开和传参概述... 15

6.2 Shell打开页面... 18

6.3 对话框与数据传递... 19

6.4 内嵌页面与参数传递... 21

7.页面结构及生命周期视频... 23

课程记录... 24

1.最简单的应用... 24

2.firstSPA.. 24

3.todoMVC.. 24

4.通过list显示服务端json文件中的数据... 24

表单与data组件的绑定... 25

5.实现单表的CRUD.. 25

6.自己框架实现后台服务... 25

7. 自己框架集成BaaS代码... 26

8. WebSocket通信应用... 26

9.播放音频视频... 26

10.调试... 26

 

 

WeX5学习笔记

1.轻松看透WeX5产品能力和技术

首先,必须理解一件事:移动和云时代的企业应用技术,说白了,也就三块:前端UI、后端服务、前端设备api。这后面,是一个事实和趋势:就是前后端已经分化,并各自独立发展:

1.前端UI

互联网和浏览器已经普及和扎根,企业应用的前端UI和样式组件,都会沿着w3c的html+css+js路线发展,资源也越来越多,比如bootstrap等。已经没有任何企业,能离开w3c的html+css+js标准,另起炉灶搞自己的了。微软试了不行,adobe试了不行,没人能行。

2 后服务端

后端和前端正好相反,技术正走向多元化。node,Python,java并存,以及PAAS、BAAS(后端即服务:Backendas a Service 公司为移动应用开发者提供整合云后端的边界服务)云服务的成熟,数据绑定也要支持多种技术和方向。

3 前端设备api

移动和设备在急剧发展,各种硬件能力会更多的加入,想想可穿戴设备吧,想想智能客厅吧,想想未来的手机吧。。。

总结起来,就是一条原则:“让UI界面归UI界面,让设备api归设备api,让后端服务归后端服务”。仅此而已!

这个原则,正是WeX5技术设计坚定遵循的原则。正是对这一原则的坚决遵循,才使得WeX5的技术如此开放强大。

而WeX5另一个强大的原因,是源于开源的力量。免费诚可贵,自由价更高。开源给你的,就是自由。开源是王道啊。

下面逐条说说WeX5强大之处,以及原因:

1.开源模式

WeX5采用的是Apache许可证开源模式,商业友好,完全免费。开发出来的应用,每一行代码都在你手里,发布部署无任何限制,自由,免费。

2.跨平台多前端应用开发,支持app、web和微信应用快速开发

WeX5对跨平台多前端应用开发的支持极好,一次开发,多平台运行。

目前,WeX5能开发的跨平台多前端应用有:

移动app(苹果ios app、安卓Androidapp)

微信应用(包括公众号、服务号和企业号应用)

企业web app(PC、平板和手机)

其他轻应用(百度直达号等)

(在企业应用市场,多平台、跨前端已成必须,而非可选!微信应用,已经势不可挡,必将颠覆移动应用的版图。在微信应用和百度直达号等轻应用的推动下,在企业移动应用领域,hybrid app也将固化其主流地位,毫无悬念)

3.高效精致的UI组件体系,完全基于主流标准和技术

 WeX5的UI组件体系是完全基于html5+css3+js,非常干净标准。

 WeX5的UI组件技术完全是开放主流,基于jquery和bootstrap(Bootstrap是Twitter推出的一个用于前端开发的开源工具包)技术,经WeX5高度优化,在移动上的表现很好,接近原生,真的很赞。

WeX5 的UI基于模块化开发,采用增强的RequireJS模块化技术

可视化拖拽设计的组件技术,WeX5已经提供了大量丰富的UI组件,并且支持引入和扩展第三方组件,大大提升了界面开发的效率和降低了难度

风格样式库基于bootstrap技术,在bootstrap基础上大大增强了适合移动的样式和组件,可轻松引入bootstrap大量丰富的样式资源并随意换肤

高效灵活的双向数据绑定技术和数据组件,使用简单能力强大

高度优化,性能接近原生。操作爽滑,拖拽、转场及动画效果很好

(我个人很认同WeX5的做法,第一,凡是业界主流的好轮子,比如jquery和bootstrap,就应该直接用,而且,WeX5做了深度优化,使app运行效果媲美原生。第二,我有技术洁癖,UI组件库,必须基于html5+css3+js这样的标准,这也是w3c统治互联网的三大基石,没的其它选择啊)

4.  本机API框架(Native APIFramework)

WeX5采用混合应用(hybrid app)开发模式。能轻松调用手机设备的系统和硬件能力,如相机、地图、LBS定位、指南针、通讯录、文件、语音、电池。。。等。

这方面,phonegap/cordova几乎是事实的标准了,很多大公司都采用。在本机框架上,WeX5有:

基于phonegap(cordova)框架

默认内嵌高性能浏览器,大大提升性能,特别是android低端机

提供微信等轻应用框架

提供了丰富的原生插件

支持引入和扩展第三方插件,任何原生app能实现的能力都可通过扩展插件实现

5.  可视化拖拽式集成开发环境IDE

WeX5的IDE基于eclipse,WeX5的主要工作是强化了可视化快速开发。提供了一个完全可视化、组件化、拖拽式开发环境。

基于eclipse开源IDE

可视化、组件化拖拽设计,完全所见即所得

向导化、模版化等工具,快速生成常见应用场景界面

全方位代码智能提示,这方面WeX5做了很多功夫,WeX5所有的UI组件,乃至手机本机插件API,在WeX5的IDE里,都能实现代码智能提示,给开发者提供极大方便

6.  全能力的调试支持和智能代码提示

开发手机app,模拟调试是关键能力,对开发者极端重要,而这也是业界现有hybrid app开发工具的软肋。WeX5对hybrid app开发提供了业界最强大的调试支持,表现真正完美。

提供全能力、一站集成的模拟调试支持。开发手机app,日常的调试几乎都是模拟调试,使用频繁度远超真机调试,WeX5提供全面、完备的模拟调试支持,表现真正完美

WeX5的模拟调试效果和真机运行效果几乎完全相同。由于WeX5的UI组件体系彻底基于html+css+js,并采用高仿真本机设备app模拟,模拟调试运行效果和真机运行效果几乎完全相同,杜绝模拟运行和真机运行不一致的问题

WeX5开放了所有的UI框架和组件源码,使得开发者能在浏览器里跟踪进入每一个组件的每一行代码,找到和排查到真正的底层原因,系统调试彻底透明,无黑盒,无死角!

支持真机调试,提供全真机和快捷真机调试模式,为开发者提供最大方便。

WeX5开放了全部原生app框架源码和本机api插件源码,开发者可以在原生开发环境(Android ADT和XCode)内,跟踪调试进入app的每一行代码里

7.  无限制、多方式、可加密的App应用打包发布

WeX5采用Apache 许可证开源协议,商业友好。而且,在开放性上,也走的极端彻底,这一点在app应用打包上得到充分体现:

打包发布无任何限制,无需任何费用。WeX5彻底开源,应用的每一行代码都在你手里,自由打包,无拘无束!

轻松打包发布成高性能的原生app,包括安卓Android的apk,苹果ios的ipa

一键发布微信应用(微信公众号、服务号、企业号均可)

一键发布成百度轻应用、web应用等

WeX5打包发布的app和应用,支持全部web资源(html+css+js)的加密,WeX5采用高强度动态密钥,每个app每次编译都会采用不同的动态密钥,真正做到一包一秘!

支持本地快捷打包、远程服务打包、原生环境编译打包等模式,给你所有想要的打包方式和方便性

彻底开源,支持原生代码调整、插件自定义和插件选择打包,真正自由

8.彻底开放的App应用后端技术和部署方式

WeX5坚决走开源、开放的道路,WeX5在支持后端技术、后端部署上,体现出极端彻底的开放性。

开放的后端技术支持,WeX5的后端完全开放,可通过http、Websocket等协议连接各种后端中间件或云服务(java、node、php、.net等)

无限制的后端部署,可以部署在任何自己选择的公有云、私有云服务器上,WeX5的部署完全开放自由,无任何限制

总而言之,WeX5是多平台、跨前端应用开发的优秀工具,业界收费的同类工具,和WeX5相比,技术要落后和老化不少。最难得的是:WeX5采用商业友好的Apache许可证开源模式,用的放心啊。

企业移动应用大潮滚滚,微信应用扑面而来,祝各位朋友用好开源的WeX5,多多发财!

2.WeX5可以怎么玩?

一、纯本地App

没任何服务请求,已经有开发好的一堆html+js,希望本地App中可以方便的使用,那可以参考默认的Native/X5工程,把自己开发好的资源放到www目录下就可以,注意工程的几个重要选项:

服务地址:http://localhost

首页: 假设你www中有一个入口的index.html,那写 /index.html

生成App包的向导中,“重新编译使用到的UI资源”一定不要选

二、关联一个网站,希望默认就打开某页

例如想把本论坛做成一个app,那可以新建一个本地App,把

服务地址:http://bbs.justep.com

首页: /forum.php

 这样生成的app,一启动就打开论坛的首页

三、UI设计器

UI2下建自己应用(例如demo),形成自己的一组页面,然后Native新建一个本地App,选择新建的资源demo,点右键“编译使用到的UI资源”,则在ww下生成标准的html+js,该资源可以放到标准 web 服务器(apache, iis, tomcat等)直接进行网络访问

四、打包神器

什么UI2,什么X5不要,我就只要一个可以生成App的环境,点这里下载

xcode,adt, 哈哈,都有

五、标准玩法

外卖为例,“WeX5 App与服务端交互原理” 有交互原理介绍。

资源打进app,bass 部署到tomcat上作为服务, 这个是推荐用法。

什么,资源咋升级?没问题,按“App资源和版本更新”将最新的资源按更新到服务器即可。

刚下载的一个WeX5,解压后运行目录的“启动WeX5开发工具.bat”和“启动WeX5运行平台.bat”,这样就可以用浏览器连接和访问,如果App不选择打包资源,那修改的资源,App 也会自动更新。

3.WeX5 App与服务端交互原理

拿WeX5自带的外卖来说举例,它由三部分组成

1. UI2/takeout 这个是页面,由页面文件.w和js以及css等构成,js中有$.ajax的请求

2. Native/外卖这个是本地app的工程,用来打包app

3. tomcat的webapps/baas 这个是服务端,提供步骤1中的$.ajax访问

启动服务

开发工具Studio中启动Tomat,这个将启动两个服务,一个是tomcat的webapps下的baas服务,另外一个是用于解析运行UI2资源的UIServer(在runtime\UIServer)。为描述方便,这里假设本机ip地址是192.168.1.1, tomcat的端口是8080

浏览器访问

浏览器输入

1

http://192.168.1.1:8080/x5/UI2/takeout/index.w

这样就可以访问外卖功能,这个在电脑浏览器或者手机浏览器都可以(电脑推荐使用chrome浏览器)。

 解释一下这个URL8080后面的x5UIServer的名字,在tomcatserver.xml中定义,具体请参考tomat的相关说明,表示访问UIServerUI2/takeout/index.w 这个会请求到UIServer后,由UIServer做编译,生成htmljs供前端使用。

 本地App

首先要生成App,先看看默认的App定义,在 Native/外卖 上点右键选择“编辑本地App”,向导中有三个重要的参数:

1. 服务地址:这里应该写 http://192.168.1.1:8080, 因为baas在这个服务上

2. 首页: 就是默认打开的页面写 /x5/UI2/takeout/index.w,这里 x5那个可以写成任意的,和前面介绍的UIServer的那个x5名字没任何关系

3. 需要打包的资源:默认选择了takeout,这里如果选择了,那UI2/takeout下的资源会被打包到App里面,也就是说tomat中没有UISever那个服务运行也是正常的,如果不选择,则首页那个就必须写成/x5/UI2/takeout/index.w,因为默认的UIServer的名字叫x5,App启动时是通过UIServer来获取页面,和浏览器访问完全相同

 补脑

如果takeout资源打包了,服务地址写 http://localhost 可否?

还真不行,因为资源中有$.ajax的请求会发到 192.168.1.1:8080/baas 上,如果写localhost,那页面打开没问题,但ajax请求会遇到传说中的跨域问题,导致失败,所以这里服务地址要写baas服务的地址。换句话说,对于资源打到App的情况,服务地址更多是告诉ajax请求当前域是谁,从而避免跨域问题(所有请求都是http://192.168.1.1:8080/xxx,但app内部做了处理,会优先找打入app的资源,没有找到的资源在去请求服务端,对于app来说,是读取本地资源还是服务端请求没任何区别,从而解决跨域问题)。当然,如果没有任何ajax请求或者用插件方式发http来访问,实际上可以写 http://localhost而如果要访问多个地址,那就只能写成 http://localhost,在配合http的插件发请求(自带的plugin.http.request插件),就不能使用jquery的了(其实纯html可以用jsonp方案,不过比较麻烦,具体baidu,推荐插件方案)。

 

4.Account示例程序

UI2/demo/account

记账本演示程序。

演示了 list 、windowReceiver, windowDialog等的用法。

在主页面中,windowDialog通过src属性指定页面w文件,将窗口指定为对话框。这样可打开对话框,并传递数据到对话框中。在对话框页面中,通过windowReceiver接收主页传递的数据、关闭对话框,并传递返回数据到主页。

 

另外,data.save()方法,触发 data 组件的 onCustomSave 事件,事件处理函数完成具体保存操作。这里实际上通过事件触发和处理机制,实现了save保存操作的重写。允许程序员实现自定义操作。

justep.Shell.showLeft();实现侧边栏切换显示状态。

 

Swing组件,实现左右侧边栏。

 

contents组件:在.w文件中使用contents组件可以实现不同页面的展现,特别是可以通过手势滑动来切换页面。contents组件使用content来展现页面,contents组件中可以包括多个content,content可以动态生成,删除,增强了页面显示的灵活性,contents组件和buttonGroup组件配合使用,使用button组件的target属性关联content,可以实现按钮和页面的绑定

 

组件路径:/UI2/system/components/justep/contents

组件标识:$UI/system/components/justep/contents/contents

 

配合其它组件使用,可实现以下功能:

 

滑动切换页面

实现图片轮换效果

模拟门户打开w页面

新增空白content,并动态创建组件

contents嵌套contents,分类切换页面

 

通过ShellImpl的contentsXid属性指定。 可在多个页面中实现切换显示。

 

       this.shellImpl = new ShellImpl(this, {

                     contentsXid : "pages",

                     wingXid : "wing",

                     pageMappings : {

                            "list" : {

                                   url :"$UI/demo/account/list.w"

                            },

                            "detail" :{

                                   url :"$UI/demo/account/detail.w"

                            },

                            "classSetting": {

                                   url :"$UI/demo/account/classSetting.w"

                            }

                     }

              });

 

 

 

 

代码触发事件,通过事件传递数据,触发操作:

       Model.prototype.classDataAfterSave =function(event) {

              // 通过Shell发出一个消息,通知其他页面分类数据已改变,并且在消息中携带了改变后的分类数据

              var classData =http://www.mamicode.com/this.comp("classData");

              justep.Shell.fireEvent("onClassChanged", {

                     "classData" :classData.toJson()

              });

       };

 

Detail.w对应的脚本detail.js中:

Model.prototype.onClassChanged = function(event) {

       this.comp("classData").clear();

       this.comp("classData").loadData(event.classData, truenullnulltrue);

    };

5.Takeout示例程序

5.1Index.w

5.1.1模型

Data和baasData的图标不同,baasData的图标 ,data的图标 。

foodData(baasData)

计算规则:

CalcPriceText: js:‘¥ ‘ + val(‘fPrice‘) + ‘元‘

calcImageURL: js:$model.transURL(‘./img/‘+val(‘fImage‘))

 

userData(baasData)

过滤条件userFilter:

fID = :user

orderData(baasData)

过滤条件userFilter:

fID = :user

 

cartData(data)

计算规则: calcMoney ---- js:val(‘fPrice‘) *val(‘fCount‘)

statusData(data)

计算规则:

calcCartSumMoneyText ---- js:‘¥ ‘ +$model.comp(‘cartData‘).sum(‘calcMoney‘) + ‘元‘

 

calcCartCountText----js:($model.comp(‘cartData‘).count()> 0) ? ‘购物车(‘ + $model.comp(‘cartData‘).count() +‘)‘ : ‘购物车‘

 

calcCanSaveOrder ----js:$model.comp(‘cartData‘).sum("calcMoney") > 0

 

calcCanClearCart ----js:$model.comp(‘cartData‘).count() > 0

 

 

payData(data)

 

 

5.1.2 UI界面

1.对话框

Src: $UI/takeout/mapActivity.w

2.主要内容

四个content显示食品、购物车、订单和我的四个页面。

四个按钮实现页面切换:foodBtn、cartBtn、orderBtn、ownBtn

切换实现:按钮的target属性设置。

布局组件contents上可通过右键菜单添加多个content:

这样做估计有一个好处,那就是主要内容都在一个.w文件里,可以共用模型的定义。

1)foodContent

使用list组件显示食品列表foodList,在list模板中使用了 media(bootstrap) 组件。media-left中显示食品图片,类型image(html),通过bind-attr-src 将image组件的src属性和foodData的列calcImageURL绑定, val(‘calcImageURL‘)。

media-body 中显示 “来一份”按钮 addCartBtn,三个output输出食品名称、描述和计算价格文本。

“来一份”按钮处理代码中,下面代码

       if(cartData.find([ ‘fFoodID‘ ], [ row.val(‘fID‘) ]).length === 0) {

       的作用是使同一食品在购物车中不能重复添加,具体份数可在购物车页面修改。也就是一种食品在购物车中只能作为一条记录出现。

       按钮的span使用bind-text属性 statusData.ref(‘calcCartCountText‘)显示购物车中的食品数量。

2)cartContent

       两个panel,一个用于显示购物车内容;一个用于显示联系人信息。

       显示购物车内容用list组件;

       显示联系人信息用了form(html),css类是 form-horizontal。formGroup(bootstrap)

       付款类型用了radioGroup,单选按钮组。单选按钮组通过itemset属性和payData模型数据关联在一起。

      

       两个按钮:清空购物车,调用cartData.clear()方法。

下单

3)orderContent

       List组件显示订单内容:

 

4)ownContent

显示用户姓名、电话、地址。

保存用户信息。

通过定位功能获取用户位置,作为地址。

5.2mapActivity.w

通过 iframe 引入map.html

在 map.html 中,通过js调用了百度地图。

问题

transURL

calcImageURL: js:$model.transURL(‘./img/‘+val(‘fImage‘))中 transURL的用法?

 

       //转换动态图片URL

       Model.prototype.transURL= function(url) {

              returnrequire.toUrl(url);

       };

过滤条件 过滤条件userFilterfID= :user:user的用法?

:user用法估计类似于SQL语句中的绑定变量。占个位置,便于外部传入数据。

Model.prototype.modelLoad 函数中,直接设置:

       this.comp(‘userData‘).filters.setVar("user",this._userID);

       this.comp(‘orderData‘).filters.setVar("user",this._userID);

media(bootstrap) 组件

http://www.uedsc.com/bootstrap-media-object.html

Bootstrap 中的多媒体对象(MediaObject)。这些抽象的对象样式用于创建各种类型的组件(比如:博客评论),我们可以在组件中使用图文混排,图像可以左对齐或者右对齐。媒体对象可以用更少的代码来实现媒体对象与文字的混排。

媒体对象轻量标记、易于扩展的特性是通过向简单的标记应用 class 来实现的。你可以在 HTML 标签中添加以下两种形式来设置媒体对象:

.media:该 class 允许将媒体对象里的多媒体(图像、视频、音频)浮动到内容区块的左边或者右边。

.media-list:如果你需要一个列表,各项内容是无序列表的一部分,可以使用该 class。可用于评论列表与文章列表。

formGroup(bootstrap)

课程中提到的form-group样式和form-control有什么实质的区别呢?form-group一般用于div,form-control一般用于置于div中的标签元素。

justep.Util.hint

显示提示信息框:

justep.Util.hint("请填写完整的用户信息", {

                            "type": "danger"

                     });

 

当前日期格式化

justep.Date.toString(new Date(),justep.Date.STANDART_FORMAT)

jQuery的deferred对象

http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html

开发网站的过程中,我们经常遇到某些耗时很长的javascript操作。其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们都不是立即能得到结果的。

通常的做法是,为它们指定回调函数(callback)。即事先规定,一旦它们运行结束,应该调用哪些函数。但是,在回调函数方面,jQuery的功能非常弱。为了改变这一点,jQuery开发团队就设计了deferred对象。简单说,deferred对象就是jQuery的回调函数解决方案。在英语中,defer的意思是"延迟",所以deferred对象的含义就是"延迟"到未来某个点再执行。它解决了如何处理耗时操作的问题,对那些操作提供了更好的控制,以及统一的编程接口。它的主要功能,可以归结为四点。下面我们通过示例代码,一步步来学习。

deferred对象有三种执行状态----未完成,已完成和已失败。如果执行状态是"已完成"(resolved),deferred对象立刻调用done()方法指定的回调函数;如果执行状态是"已失败",调用fail()方法指定的回调函数;如果执行状态是"未完成",则继续等待,或者调用progress()方法指定的回调函数(jQuery1.7版本添加)。前面部分的ajax操作时,deferred对象会根据返回结果,自动改变自身的执行状态;但是,在wait()函数中,这个执行状态必须由程序员手动指定。dtd.resolve()的意思是,将dtd对象的执行状态从"未完成"改为"已完成",从而触发done()方法。类似的,还存在一个deferred.reject()方法,作用是将dtd对象的执行状态从"未完成"改为"已失败",从而触发fail()方法。

jQuery提供了deferred.promise()方法。它的作用是,在原来的deferred对象上返回另一个deferred对象,后者只开放与改变执行状态无关的方法(比如done()方法和fail()方法),屏蔽与改变执行状态有关的方法(比如resolve()方法和reject()方法),从而使得执行状态不能被改变。

6.页面间交互视频

6.1 页面打开和传参概述

打开页面的三种方式:

使用Shell,例如 UI2/portal/sample/index.w,这种方式不返回参数;

打开对话框;

使用内嵌页面(WindowContainer);

 

传参数的三种方式:

?参数,进入URL,

Params,#!参数,通过序列化也能进入URL;

Params.data,不支持序列化,不进入URL,所以不能随链接一起分享。

 

传参数的例子:

UI2/demo/page/index.w ,这个首页中,

 

点击按钮

打开页面

演示打开页面的方式和打开页面传参数。

上面页面文件是 interactive/page.w

6.2 Shell打开页面

 

第一种代码:

    //"p2"是index.w中 pageMappings定义的页面标识

       justep.Shell.showPage("p2");

第二种代码:

    var url = require.toUrl("./page2.w");

       justep.Shell.showPage(url);

 

三种参数传递:

    var url = require.toUrl("./page2.w?p1=p1Value&p2=p2Value");

       var params = {

           a1: "a1Value",

           a2: 2,

           data: {

              d1: "d1Value",

              d2: "d2Value"

           }

       }

       justep.Shell.showPage(url,params)

 

require.toUrl 相对路径转换为绝对路径。

参数接收,都在model组件的onParamsReceive事件中。此处是在page2.w中。可在该事件处理中通过event.params访问后两种参数,也可通过this.params随时访问后两种参数。

6.3 对话框与数据传递

 

打开对话框并传递参数到对话框:有两种方法。不传参数可以使用按钮关联open操作。传参数可以向下面一样写代码。通过写代码可实现每次打开不同的页面。

Model.prototype.button1Click = function(event){

       var dialog = this.comp("dialog");

       var url = require.toUrl("./dialog.w?p1=参数1&p2=参数2");

       dialog.open({

           src: url,

           params: {

              a1: "简单数据a1",

              a2: 2,

              //data是特殊的参数, 这部分内容不能被分享

              data: {

                  //将一个函数传递给对话框

                  fn: function(){        

                     alert("将一个函数传到对话框中");

                  }, 

                  //将data中的一行数据传给对话框

                  data1: this.comp("data1").getCurrentRow().toJson()

              } 

           }

           

       })

    };

 

对话框dialog.w中接收参数:

Model.prototype.modelParamsReceive= function(event){

       var context = this.getContext();

       

       //获取URL中的参数

       var p1 = context.getRequestParameter("p1");

       var p2 = context.getRequestParameter("p2");

       var buf = "来自url的参数: p1=" + p1 + ", p2=" + p2 + "\n";

       

       //获取简单参数

       buf += "简单参数:params.a1=" + event.params.a1 + ",params.a2=" + event.params.a2 + "\n";

       

       //获取复杂参数

       buf += "复杂参数:\n"

       if (event.params.data){

           buf += "    params.data.fn=" + event.params.data.fn + "\n";

           this.comp("dlgData").loadData([event.params.data.data1]);

           this.comp("dlgData").first();

       }

       alert(buf);

    };

 

对话框关闭并返回参数给主窗口 page.w

    Model.prototype.button3Click = function(event){

       this.owner.send(this.comp("dlgData").getCurrentRow());

       this.close();

    };

this.owner是谁?是page.w中的dialog组件。

 

主窗口page.w接收对话框dialog.w返回的数据:

    Model.prototype.dialogReceive = function(event){

alert("页面接收对话框架返回的数据:" +JSON.stringify(event.data.toJson()));

    };

对话框的属性

onClose指向 dialogClose函数。

onReceive指向dialogReceive函数。

src指向./dialog.w。

 

什么时候将返回数据写入主页的data1组件的呢?用的是对话框的mapping机制。对话框mapping属性点击打开对话框

注意对话框事件onReceive和onReceived的区别。

onReceive在mapping之前进行,onReceived在mapping之后进行。

6.4 内嵌页面与参数传递

page.w页面的containerContent中有两个windowContainer组件,windowContainer1指向./page3.w,windowContainer2指向./page4.w。这样就把page3和page4作为内嵌页面放到了page中。

windowContainer1

src属性./page3.w?p1=p1&p2=p2同时指定了url参数。

Params指定{a1: "a1", a2: "a2"}了第二种参数。

Page3.js中接收了参数:

Model.prototype.modelParamsReceive= function(event){

       var context = this.getContext();

       

       //获取URL中的参数

       var p1 = context.getRequestParameter("p1");

       var p2 = context.getRequestParameter("p2");

       var buf = "来自url的参数: p1=" + p1 + ", p2=" + p2 + "; ";

       

       //获取简单参数

       buf += "简单参数:params.a1=" + event.params.a1 + ",params.a2=" + event.params.a2 + "; ";

       

       //获取复杂参数

       buf += "复杂参数:\n"

       if (event.params.data){

           buf += "    params.data.d1=" + event.params.data.d1 + "; ";

           buf += "    params.data.d2=" + event.params.data.d2 + "; ";

       }

       

       var id = this.getIDByXID("container");

       $("#" + id).text(buf);

    };

显示所有参数按钮演示了如何在页面中获取使用参数:

Model.prototype.button1Click = function(event){

       var context = this.getContext();

       

       //获取URL中的参数

       var p1 = context.getRequestParameter("p1");

       var p2 = context.getRequestParameter("p2");

       var buf = "来自url的参数: p1=" + p1 + ", p2=" + p2 + "\n";

       

       //获取简单参数

       buf += "简单参数:params.a1=" + this.params.a1 + ", params.a2=" + this.params.a2 + "\n";

       

       //获取复杂参数

       buf += "复杂参数:\n"

       if (this.params.data){

           buf += "    params.data.d1=" + this.params.data.d1 + "\n";

           buf += "    params.data.d2=" + this.params.data.d2 + "\n";

       }

       alert(buf);

    };

返回参数按钮代码:

    Model.prototype.button2Click = function(event){

       this.owner.send({r1: "r1Value"});

    };

向主页page.w发送了名为r1的参数,值为r1Value。

主页page.w中下面代码接收并显示了参数r1的值。

    Model.prototype.windowContainer1Receive = function(event){

       alert("接收到内嵌页面的返回数据:r1=" + event.data.r1);

    };

 

主页page.w中“刷新内嵌页面”按钮执行代码:

    Model.prototype.button8Click = function(event){

       var url = require.toUrl("./page3.w?p1=p1ValueNew&p2=p2NewValueNew");

       var params = {

           a1: "a1ValueNew",

           a2: 20,

           data: {

              d1: "d1ValueNew",

              d2: "d2ValueNew"

           }

       }

       this.comp("windowContainer1").load(url, params);

    };

代码重新装入内嵌页面page3,并传递了新的参数。

Load方法智能判断,src没变只传参数;src变了刷新页面。Refresh页面会强制刷新页面。

windowContainer2

src属性./page4.w指定了内嵌页面。

Params属性{data: $model.data1}将主页模型中数据组件data1的值传递给内嵌页面。

页面./page4.w中分别使用input和list显示了参数数据:$model.params.data。

 

让人比较意外的是,这种数据关联居然是双向的:即主页数据改变可实时传递到内嵌页面,内嵌页面数据改变也可实时传递到主页。原因是主页和内嵌页面UI绑定的是同一个对象,就是data1。

主页和内嵌页面可互相访问对方的model组件

7.页面结构及生命周期视频

 

课程记录

1.最简单的应用

Hello

介绍应用创建,app打包

2.firstSPA

自己利用页面向导创建程序。不用WeX5网站提供的视频中的方法。

3.todoMVC

       介绍模型、窗口组件、事件、js代码等

4.通过list显示服务端json文件中的数据

       练习list组件和data组件的用法

goosData.json

参考 demo/taobao /list.w

1)  新建listJsonData应用

2)  复制demo/taobao/cart文件夹。里面有图片和json格式的数据文件。

3)  创建标准页面 index.w

4)  页面model中添加data组件goodsData,根据json数据文件格式,建立数据模型列定义

Index.js 中添加代码 (代码参考demo/taobao/list.w中同名函数)

Model.prototype.loadDataFromFile= function(url, objData, operation) {

       if (operation) {

           objData.clear();

       }

       $.ajaxSettings.async = false;

       $.getJSON(url, function(data) {

           objData.loadData(data);

       });

    };

 

    // 获取商品列表

    Model.prototype.goodsDataCustomRefresh = function(event) {

       

       var url = require.toUrl("./cart/json/goodsData.json");

       this.loadDataFromFile(url, event.source, true);

    };

5)  goodsData的onCustomRefresh事件绑定函数goodsDataCustomRefresh

6)  index.w 的panel面板的content中添加scrollview组件。Scrollview实现下拉刷新,上划加载更多数据。

7)  scrollview的中间content中添加list组件,设置data属性值为goodsData。list组件会自动根据关联data数据循环显示。

8)  在li中添加row组件,row中添加output,引用data中当前行的列。

9)  启动tomcat,运行index.w。

10) 知识点讲解:参考教材的scrollview,list,data组件。

 

 

表单与data组件的绑定

 

5.实现单表的CRUD

       通过baas服务。

       包括通过Java实现自定义的Action

       Baas打包部署

       参考:WeX5后端服务教程.zip

6.自己框架实现后台服务

自己有j2ee的后台服务可以提供数据,wex5应该怎么访问呢,可以不用baas吗?

可以使用ajax直接访问,不过返回的json数据格式要保证能加载到data组件中http://doc.wex5.com/?p=4932

 或者是像这样的:/UI2/demo/tuniu/json/cityData.json建议集成3.2.1的baas,这样数据交互会简单些可以看看baas服务视频:http://wex5.com/cn/1-wex5#06

  打包下载的那个视频(3.2.1以前版本的baas)

 

 

7. 自己框架集成BaaS代码

 

8. WebSocket通信应用

9.播放音频视频

10.调试

       一种需求是界面基本不变,调试后端服务。这时可在native文件夹创建app,然后,右键菜单选择编译UI资源,成功后将www文件夹内的文件复制到myeclipse调试用的tomcat服务器应用程序部署文件夹内,作为一个应用程序即可。

       在这种情况下,通过浏览器调试UI中的脚本程序是可以的。

       另外一种需求是后台服务基本不变,主要是开发调试UI。这时,应该把后端服务部署到WeX5开发环境所用的tomcat服务下。但是这个还没有尝试。

WeX5学习笔记