在上一篇文章讲到SFData的设计的时候,已经简单的提到了数据组件要实现的功能,实际上,数据组件,是SFData的一个插件,这个插件可以调用 SFData的所有的方法和事件,用来完成一些附加的功能和数据逻辑,例如,我们现在已经使用数据组件功能实现了以下逻辑:
    1.SFDataCalculateTimeComponent,在任务的起止时间发生变化的时候,检查父任务的起止时间,保证每个概要任务的起止时间和其所有子任务的起止时间范围一致;
    2.SFDataOutlineComponent,完整的实现任务的大纲级别(OutlineLevel和OutlineNumber)的功能,在任务添加、移动、删除的时候,所有的任务的大纲级别都跟随变化
    3.SFDataIdComponent完整的实现任务的ID的功能,在任务添加、移动、删除的时候,保持ID始终作为任务的顺序号
    4.SFDataLogging,实现数据的更新日志,将数据的更改统一都记录下来,以便统一发送到数据库保存。
    实际上,这只是数据组件的一些简单的应用而已,依托SFData提供的强大功能,实际上可以完美的实现很多自定义的功能,例如数据的向上汇总,某些属性的自动设置等等。

    在数据组件机制产生之前,我们曾经通过taskpropertyread实现过一个功能:某个任务不是大纲,而且任务的时间在10天以上的时候,则使用 特别的样式来标识出来(标红),以前虽然实现了这个功能,但是有明显的问题:假如一个任务开始只有9天,后来被更改为11天,这个时候,这个任务实际上已 经应该被标红了,可是时间的更改没有引起列表显示的刷新(列表根本不知道还需要刷新显示),因此会出现问题。
    假如通过数据组件来实现,我们就可以在taskregister事件发生的时候根据任务的属性来设置任务的样式,然后在aftertaskupdate的时候根据新的任务属性来重设任务的样式,这样就可以比较完备的实现需要的功能。
    在提供这个例子之前,我们看看数据组件需要实现哪些接口(因为数据组件初始化的时候可以得到SFData对象,因此SFData和相关的实体类的属性和方法都可以使用):
方法名称 返回值 说明
initialize(data) null 初始化此数据组件
remove() null 停用此数据组件
depose() null 销毁此数据组件

    可以看到,这个需要实现的接口非常简单(尤其是在看了数据适配器的一长列接口列表之后),其实最重要的是在initialize方法之中对data对象进行处理,捕获一些事件以便达到控制数据的目的。
    我们下面看一个实现数据适配器的范例,该范例实现以上说明的功能。

function MyAutoClassNameComponent(timeSpan)
{
this.timeSpan=timeSpan?timeSpan:10*24*60*60*1000
}
MyAutoClassNameComponent.prototype=new SFDataComponent();//在这里继承SFDataComponent
MyAutoClassNameComponent.prototype.initialize=function(data)
{ //绑定事件
this.listeners=[
SFEvent.bind(data,"taskregister",this,this.onTaskRegister),
SFEvent.bind(data,"aftertaskupdate",this,this.onTaskUpdate),
];
}
MyAutoClassNameComponent.prototype.setClassName=function(task)
{
//这个函数设置任务的ClassName属性,只有符合条件,才设置为TaskImportant,否则留空(置为默认)
var name="";
if(!task.getProperty("Summary") && task.getProperty("Finish").valueOf()-task.getProperty("Start").valueOf()>this.timeSpan)
{
name="TaskImportant";
}
task.setProperty("ClassName",name);
}
MyAutoClassNameComponent.prototype.onTaskRegister=function(task)
{ //在任务初始化的时候设置值
this.setClassName(task);
}
MyAutoClassNameComponent.prototype.onTaskUpdate=function(task,name,value,beforeValue)
{ //在有关联的三个属性变化的时候重新设置值
if(name=="Summary" || name=="Finish" || name=="Start")
{
this.setClassName(task);
}
}
MyAutoClassNameComponent.prototype.remove=function()
{
var listenr;
while(listenr=this.listener.pop()){SFEvent.removeListener(this.listener)}
}

    虽然需要实现的接口并不是很多,但是实现一个数据组件似乎并不容易,因为你必须非常了解你需要操作的属性,并且对SFData的机制也有有一定的了解才行,不过你一旦了解之后,就可以实现很多复杂的逻辑了,而且,向日葵甘特图也就能够完美的与应用结合在一起了。
posted on 2009-05-20 07:04  运筹帷幄  阅读(714)  评论(0编辑  收藏  举报