分享
 
 
 

&#106avascript事件驱动模型的不完全剖析

王朝html/css/js·作者佚名  2006-11-24
窄屏简体版  字體: |||超大  

由于javascript并不是真正意义上“面向对象”的语言,所以,在实现事件驱动模型的时候,总是会遇到一些困难。

当然这里指的事件驱动并不是指javascript固有的事件处理机制或者DOM的事件模型,而是指类似C#或者Java的那种事件模型。

javascript在处理事件驱动的时候最大的问题在于"this指针"困惑。

例如:<input type="button" onclick=function(){alert(this.value);} value="Hello World!"/>

这里的this指针毫无疑问是没有问题的

但是,<input type="button" id="button1"/>

var objBtn = document.getElementById("button1");

objBtn.attachEvent('onclick', EventHandler);

function EventHandler()

{

alert(this.value);

}

运行这个脚本很吃惊地发现得到的是完全错误的结果

因为这里的this并不是objBtn这个input对象!而是全局的window对象!

类似的问题在javascript中还会经常出现

再比如一个更复杂的应用:

function mainForm(form)

{

this.form = form;

this.button1 = form.buttonOK;

this.button2 = form.buttonCancel;

this.button1.onclick = Button1_Click; //为按钮注册单击事件

this.button2.onclick = Button2_Click;

mainForm.prototype. Button1_Click = function()

{

alert(this.button1.value);

}

mainForm.prototype.Button2_Click = function()

{

this.form.style.display = 'none';

}

}

本来一段挺“漂亮”的代码,却不能正确运行,为什么呢?原来问题还是在this上,button1_Clicked和button2_Clicked两个函数虽然是mainForm类的成员函数,但是他们是被this.button1.onclick和this.button2.onclick调用(不完全准确的说法)的,所以函数中的this指得是button1和button2两个对象!这很令人困扰,不是吗?

为了解决这个问题,必须要保证函数调用者是mainForm对象而不是button或者其他的什么成员,为此,我思考出一种事件注册的机制,将上面的代码写成:

this.button1.ClickEventSender = this;

this.button1.onclick = function(){this.ClickEventSender.Button1_Click(this.ClickEventSender,self.event);}

mainForm.prototype.Button1_Click = function(object, sender)

{

alert(this.button1.value);

}

就得到了正确结果。

于是,一种完全的基于“后台代码”的“事件驱动”模型慢慢成型,下面是一段简短的Demo代码:

//后台代码

//事件驱动框架(演示)

//2004-11-16 Created

//2004-11-17 Modified

//ControlDemo.js

function ControlDemo(page)

{

//初始化Page

if (page == null)

{

page = self;

}

if (page != self)

{

//Do sth. here...

}

this.page = page;

//Properties

this.keyPressed = 0;

//Controlable Entities

//PageBody 注册PageLoad事件

this.body1 = page.document.getElementById("main");

this.page.PageLoadEventSender = this;

this.body1.onload = function(){this.PageLoadEventSender.PageLoad(this.PageLoadEventSender,page.event);}

//Button1 注册Click事件

this.button1 = page.button1;

this.button1.value = "确定";

this.button1.ClickEventSender = this;

this.button1.onclick = function(){this.ClickEventSender.Button1_Click(this.ClickEventSender,page.event);}

//Button2 注册Click事件

this.button2 = page.button2;

this.button2.value = "取消";

this.button2.ClickEventSender = this;

this.button2.onclick = function(){this.ClickEventSender.Button2_Click(this.ClickEventSender,page.event);}

//Textbox1 注册KeyUp、MouseMove事件

this.textbox1 = page.textbox1;

this.textbox1.style.width = "100%";

this.textbox1.rows = 10;

this.textbox1.KeyUpSender = this;

this.textbox1.onkeyup = function(){this.KeyUpSender.Textbox1_KeyUp(this.KeyUpSender,page.event);}

this.textbox1.MouseMoveSender = this;

this.textbox1.onmousemove = function(){this.MouseMoveSender.Textbox1_MouseMove(this.MouseMoveSender, page.event);}

//Labels

this.label1 = page.document.getElementById("label1");

this.label2 = page.document.getElementById("label2");

this.label3 = page.document.getElementById("label3");

//EventHandlers 事件处理函数

ControlDemo.prototype.PageLoad = function(sender,event)

{

this.page.defaultStatus = "事件驱动框架演示~~";

this.page.resizeTo(600,400);

}

ControlDemo.prototype.Button1_Click = function(sender,event)

{

alert("Hello ^_^");

}

ControlDemo.prototype.Button2_Click = function(sender,event)

{

if (page.opener == null)

{

page.opener = page;

}

page.close();

}

ControlDemo.prototype.Textbox1_KeyUp = function(sender, event)

{

this.keyPressed++;

this.label1.innerText = this.keyPressed;

this.label2.innerText = this.textbox1.value.length;

this.label3.innerText = event.keyCode;

}

ControlDemo.prototype.Textbox1_MouseMove = function(sender, event)

{

this.page.status = "鼠标位置:x="+event.x+" y="+event.y;

}

}

<!--前台页面-->

<html>

<head>

<title>事件驱动框架演示</title>

</head>

<body id = "main">

<div align="center" id="div1">

<textarea name="textbox1" id="textbox1"></textarea><br/>

键盘点击次数为<span id="label1">0</span>次,共键入<span id="label2">0</span>个字符,最后输入的字符码为

<span id="label3">0</span>

<br/>

<input type="button" name="button1" id="button1"></input>

<input type="button" name="button2" id="button2"></input>

</div>

</body>

</html>

<script language="javascript" type="text/javascript" src="ControlDemo.js"></script>

<script language="javascript" type="text/javascript">

var demo = new ControlDemo();

</script>

是不是感觉页面上的代码很简洁?

几乎只是放置对象和构造类,其他什么也不做。

而编写后台代码是不是让用asp.net的朋友有一种“似曾相识”的感觉?

虽然不敢说一定好,但,这就是javascript的另类力量。^^

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有