JavaScript
虽着
Ajax
应用越来越多,也变得越来越重要,越来越多的“网络版”软件以其眼花缭乱的异步加载刷新让人感触到
Ajax
的威力,越来越多的程序员们也开始关注于
JavaScript
的学习,以至于慢慢的发现
JavaScript
完全由能力担任所有
UI
层编码的重任。
SOA
这盘菜被个大厂商炒了又炒,
WebService
渐渐成为标准的传输方式,
Soap
被越来越多的人认识。这个时候人们发现
JavaScript
能够调用
WebService
,于是有人开始试水了。不得不说用
Javascipt
完全可以作为为
UI
层的骨架,
UI
层的逻辑开发对于
Javascipt
简直就是得心应手,显示更不用说,传输用WebService,哈哈,不再需要那么多
WebForm
控件,让C#去更多的关注如何实现业务去吧。
但对于
JavaScript
很多人不是很了解,尤其是对于大型
RIA
程序来说,一堆堆的脚本对于习惯了
C#
的程序员简直就是恶梦。就像每个人当初学
C#
一样,
Petshop
是一门不可多得的教材,当
TIBCO
宣布
GI
开源的时候,人们发现这才是
JavaScript
中最好最重量级的教材。
我想一起与大家学习
GI
中值得学习的部分,学习
Javascipt
怎么在大型
RIA
中发挥作用。
再简单介绍一下GI_Builder,GI_Builder是TIBCO公司开发的一套基于Javascipt开发的用开发开JavaScript的IDE,当然也包括一套Framework,类似于VS2005,只需要你拖拖拽拽就能实现页面上的,实现很多大家梦寐以求的Javascipt端的控件,Tab,Tree,Grid,甚至于更佳神奇的在Firefox下用SVG比表示,在IE下用VML表示的Chart。相信这些东西如何实现肯定谁都非常感兴趣。
好吧我们先从写基础的开始,看看大程序为了实现整个功能的运行都做了些什么。大多数人都知道,Ajax程序是以事件驱动为基础的,而实现一个事件的注册和广播也是很多框架中必要的设计,GI中是如何实现事件的机制的呢。
我们先来看这样一段伪事件的实现:
ClassA
=
function
()
{
//
声明事件
this
.onAdd
=
function
(){
return
false
;}
this
.Add
=
function
(a,b)
{
var
c
=
a
+
b;
//
执行事件
if
(
typeof
(
this
.onAdd)
==
"
function
"
)
this
.onAdd();
return
c;
}
}
ClassB
=
function
()
{
this
.AlertAdd
=
function
()
{
this
;
//
这里让大家看点东西,嘿嘿
alert(
"
Add
"
);
}
this
.Test
=
function
()
{
var
a
=
new
ClassA();
//
绑定事件
a.onAdd
=
this
.AlertAdd;
a.Add(
1
,
1
);
}
}
由于
Javascipt
太灵活了,所以我有了可乘之机,用了一个方法,然后动态的替换它,这样就执行的时候就可以动态的执行我的那个方法咯。哈哈,好像挺完美的吧,这么简单个东西这样就搞定了,可惜这里有点问题要解决,那就是
this
;这个东西,呵呵。由于
AlertAdd
这个方法里面的内容都指向了
onAdd
方法了,确切地说他是在
ClassA
的
scope
里面运行的,这里的
this
就变成了
ClassA
了,DOM中的事件也和这种情况差不多,具体和this的作用范围有关,乱了吧,想必很多人都遇到过这样的问题,哈。
于是乎Asp.net Ajax中出现了这样的一个东西:
function
Function.createDelegate(instance,method)
{
return
function
(){
return
method.apply(instance,arguments);};
}
这个东东的确好用,我经常用他也。一个apply成为了我们救星,可是又一个问题出现了我们在.net中可以一个劲儿的+=然后再+=,最后全都执行了,怎么一下子搞那么多事件。如何才能让Javascript中也实现这样的复杂机制呢?要想知道GI中如何实现,且听下回分解。
太困了,明天接着写吧,还要上班、上班呢啊 。
---------------------------------------------------------------------12小时后----------------------------------------------------------------------------
书接上回,咱们接着说事件的实现,一醉解千愁同志正解,就原理来说的确是一个Array就能来搞定,当然GI中为了实现不同的事件时用一个Object来实现的。但具体怎么实现的呢,还是来看GI的同志们怎么实现的吧。
在JSX30.js中有这样的一些代码:
然后当然就是事件的注册了,事件的注册需要什么?需要知道注册到什么事件上就是onXXX,还需要知道绑定到哪个方法上,于是乎evtPub._subscribe = function(strSubject, objTarget, strMethod) 方法出现了
/*
@jsxobf-clobber
*/
evtPub._subscribe
=
function
(strSubject, objTarget, strMethod) {
if
(
this
._evtpubreg
==
null
)
/*
@jsxobf-clobber
*/
this
._evtpubreg
=
{};
var
list
=
this
._evtpubreg[strSubject];
if
(list
==
null
)
list
=
this
._evtpubreg[strSubject]
=
[];
list.push([objTarget, strMethod]);
};
看这些参数,首先strSubject就是我们所说的onXXX,关于后面的两个参数是什么,我们来看看事件是如何执行的再说。
来广播了:
/*
@jsxobf-clobber
*/
evtPub._publish
=
function
(objEvent) {
if
(
this
._evtpubreg
!=
null
) {
var
list
=
this
._evtpubreg[objEvent.subject];
if
(list) {
if
(objEvent.target
==
null
)
objEvent.target
=
this
;
list
=
list.concat();
//
defensive copy
for
(
var
i
=
0
; i
<
list.length; i
++
) {
if
(
typeof
(list[i][
0
])
==
"
function
"
)
list[i][
0
](objEvent);
else
list[i][
0
][list[i][
1
]](objEvent);
}
}
}
};
先声明一下,objEvent是GI中自己实现的一个Event类,里面有个属性subject就是那个onXXX。好了,看这个方法中,在执行事件之前做了个判断也就是说objTarget会有两种形式Object和function所以说他注册的话也会有两种方法咯:
objApp._queue._subscribe("qstart", objApp._progress, "onQueueStart");
objApp._queue._subscribe("qdone", function() {…});
当然第一种方式是主要的使用方式,objTarget是调用方法所属的引用,strMethod是要调用的方法
另外,还需要看以下这个list = list.concat();我一直都不太明白,我猜想这个是为了线程安全的,在publish的时候如果再注销这个事件就会发生问题。还请高人指点……
最后当然是事件的注销了:
/*
@jsxobf-clobber
*/
evtPub._unsubscribe
=
function
(objTarget) {
if
(
this
._evtpubreg
!=
null
) {
for
(
var
subject
in
this
._evtpubreg) {
var
list
=
this
._evtpubreg[subject];
for
(
var
i
=
0
; i
<
list.length; i
++
) {
if
(list[i]
==
objTarget)
list.splice(i
--
,
1
);
}
}
}
};
/*
@jsxobf-clobber
*/
evtPub._evtcleanup
=
function
(objEvent) {
delete
this
._evtpubreg;
};
/*
@jsxobf-clobber
*/
evtPub._import
=
function
(objTarget) {
objTarget._subscribe
=
this
._subscribe;
objTarget._unsubscribe
=
this
._unsubscribe;
objTarget._publish
=
this
._publish;
objTarget._evtcleanup
=
this
._evtcleanup;
};
注销,值得一提的就是import方法,这是什么?继承-_-b….
也就是说在你的类里面需要执行以下import的方法,然后你的类里面就这些方法就都用了,不就是个call()的功能-_-b…