引言
Cube是基于Jquery和KnockJS的前端组件库,它遵循AMD的模块化规范。下面是一个典型的cube页面
使用
1. 导入cube组件库
将Cube组件库导入项目的resources目录下
2. 新建主页html并引入cube
新建目录,新建html文件,引入framework.js,因为Cube组件都遵循AMD的模块化规范,这里还要引入require.js。页面加载时,会先加载framework.js,该js会自动加载基本的js组件,这里CUBE全局变量被挂在到window上了,然后加载require.js。等require.js加载完成后,会执行require.js标签上的data-main属性对应的js文件,这里就是我们主程序的入口了。
3. 新建首页js
model.js 类似下面的代码,当然这个model.js的名称是可以变的。define([一个数组], function(和数组里的内容一一对应) {},是AMD的编码规范,前面数组表示引用哪些模块(模块本身必须是符合AMD规范的,这里的require.js是南瑞改造的,代码),后面function的入参表示那些模块使用哪些名称去使用。具体的模块可以参考framework.js里的代码。
define(["sammy", "JSONUtil","RESTClient"], function(sammy, jsonUtil,RESTClient) {
var PageViewModel = function() {
var self = this;
//假装有很多代码
cube.endViewModel(self, params);
};
var pvm = new PageViewModel();
$(document).ready(function(e){
cube.startWebPage(pvm);
});
});
4. 新建页面存放文件夹pages
然后再model.js对应的目录下新建 pages目录,名称不可随意更改,因为framework.js里写死了,之后我们新建一个js和一个相对应的html,注意:html文件的文件名最后一定是view.html,js文件的最后一定是viewmodel.js,这也是framework.js里写死的。
viewmodel.js中的内容类似下面的结构,和首页的js稍微有些不同。因为不可能从两个不同的地方启动应用,会出现下面报错。
define(["RESTClient"], function(RestClient) {
var PageViewModel = function(params) {
var self = this;
cube.endViewModel(this, params);
};
return PageViewModel;
});
5. 代码目录结构与范例
常见的代码路径类似下面的结构,其中hello-world.html是首页,demo.js是首页js,default-config.js是cube的一些默认选项配置,dialog下面是一个测试页面。
附上代码:
cube-demo.zip
简单看下首页内容
<!-- 工具栏组件 -->
<toolbar id="homeTool" params="
toolbarContent: toolbarContent,
showtext:true,
onItemClick: onItemClick
"></toolbar>
<!-- 标签页容器 -->
<tabcontainer params="
tabContents: tabContents,
selectedTabRoute: selectedTabRoute
"></tabcontainer>
define(['sammy', 'JSONUtil','RESTClient'], function(sammy, jsonUtil,RESTClient) {
var PageViewModel = function(params) {
console.log('home');
var self = this;
self.toolbarContent = [ {
group : [
{ text : '页面1', icon:'' ,func : 'toPage1' },
{ text : '页面2', icon:'' ,func : 'toPage2' }
]
}];
self.onItemClick = function(e) {
switch (e) {
case 'toPage1':
self.selectedTabRoute('#dialog');
break;
case 'toPage2':
self.selectedTabRoute('#text');
break;
default:
break;
}
}
self.tabContents = [{
title : '页面1',
route : '#dialog',
// content: '省级统计内容 ',//当content属性存在时优先显示其内容,否则显示templateOptions配置的页面
templateOptions: {
name: 'demo.dialog.dialog',
params: {title: '测试页面'}
//type: 'iframe'
//iframeHeight: '500px'
}
}, {
title : '页面2',
route : '#text',
content: '这是一段测试的文字 '//当content属性存在时优先显示其内容,否则显示templateOptions配置的页面
}];
self.selectedTabRoute = cube.obj('#dialog');// 这里使用了被观察者对象,下面简称可变对象
cube.endViewModel(self, params);
};
var pvm = new PageViewModel();
$(document).ready(function(e){
cube.startWebPage(pvm);
});
});
在页面中使用的对象或者方法等,需要优先挂载到 PageViewModel对象上,即代码中的self上,如果该属性不是一个固定值,是个可变对象,则你需要使用cube.obj或者cube.array方法,获得一个被观察者对象/数组。
观察者模式各位应该不会陌生,当被观察对象发送改变时,观察者能做出相应的处理,这里也是一样。代码中将标签页的selectedTabRoute属性设置成了被观察者,当我点击相应按钮时,修改了相应的值,标签页容器对象观察到这个改变,就会自动切换分页了。另外,有点类似于jquery中的各种属性设置,调用有参函数可以设置被观察者的值,无参函数可以获得被观察者的值。
6. 获得组件对象和方法调用
当我们查阅API文档时,会发现组件存在方法,而我们上面演示的,都是自动绑定的,如何调用方法是个问题。cube提供了一个api帮助我们去拿到相应的组件实例对象。
cube.getPageViewModelByNode(传入jquery对象);
为了避免使用jquery难以获得相应组件,或者获得了错误的组件,再给组件设置ID时应尽量独特,不重复。另外复合组件,比如form表单里的editor编辑器等,也可以用同样的方法去获得值。
7. 父子页面之间传值
一般父页面展示子页面的时候,都存在一个叫templateOptions的值,我们可以将要传递的值放入它的params字段中,上面例子做些简单修改。
- hello-world.html增加一个label变成下面的
<!-- 工具栏组件 -->
<toolbar id="homeTool" params="
toolbarContent: toolbarContent,
showtext:true,
onItemClick: onItemClick
"></toolbar>
页面1的输入: <cubelabel params="text: text"></cubelabel>
<!-- 标签页容器 -->
- demo.js 增加text属性并传入页面1的templateOptions中
self.text = cube.obj();
self.tabContents = [{
title : '页面1',
route : '#dialog',
// content: '省级统计内容 ',//当content属性存在时优先显示其内容,否则显示templateOptions配置的页面
templateOptions: {
name: 'demo.dialog.dialog',
params: {text: self.text}
//type: 'iframe'
//iframeHeight: '500px'
}
}, {
title : '页面2',
route : '#text',
content: '这是一段测试的文字 '//当content属性存在时优先显示其内容,否则显示templateOptions配置的页面
}];
- dialogviewmodel.js 修改下fields
// 查询框字段
self.fields = [
{ name : "taskType", caption : "任务类型",editorType : "TextEditor", value: cube.obj('current'), visible: false },
{ name : "facilityName", caption : "设备名称",editorType : "TextEditor", value: params.text},
{ name : "eventlevel", caption : "事件等级",editorType : "DropDownEditor", list:[
{ value: "level1", text: "一级" },
{ value: "level2", text: "二级" },
{ value: "level3", text: "三级" },
{ value: "level4", text: "四级" }
]},
{ name : "periods", caption : "期数", editorType : "DropDownEditor"},
{ name : "beginTime", caption : "停电开始时间",editorType : "DateTimeEditor",formatString: "yyyy-MM-dd "},
{ name : "endTime", caption : "停电结束时间", editorType : "DateTimeEditor",formatString: "yyyy-MM-dd "}
];
然后刷新页面测试下。