目录
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(在runtimeUIServer)。为描述方便,这里假设本机ip地址是192.168.1.1, tomcat的端口是8080
浏览器访问
浏览器输入
1
http://192.168.1.1:8080/x5/UI2/takeout/index.w
这样就可以访问外卖功能,这个在电脑浏览器或者手机浏览器都可以(电脑推荐使用chrome浏览器)。
解释一下这个URL:8080后面的x5是UIServer的名字,在tomcat的server.xml中定义,具体请参考tomat的相关说明,表示访问UIServer,UI2/takeout/index.w 这个会请求到UIServer后,由UIServer做编译,生成html和js供前端使用。
本地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 =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, true, null, null, true);
};
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);
};
过滤条件 过滤条件userFilter中 fID= :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 + " ";
//获取简单参数
buf += "简单参数:params.a1=" + event.params.a1 + ",params.a2=" + event.params.a2 + " ";
//获取复杂参数
buf += "复杂参数: "
if (event.params.data){
buf += " params.data.fn=" + event.params.data.fn + " ";
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 += "复杂参数: "
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 + " ";
//获取简单参数
buf += "简单参数:params.a1=" + this.params.a1 + ", params.a2=" + this.params.a2 + " ";
//获取复杂参数
buf += "复杂参数: "
if (this.params.data){
buf += " params.data.d1=" + this.params.data.d1 + " ";
buf += " params.data.d2=" + this.params.data.d2 + " ";
}
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服务下。但是这个还没有尝试。