MVC模式是"Model-View-Controller"的缩写,中文翻译为"模式-视图-控制器"。MVC应用程序总是由这三个部分组成。Event(事件)导致Controller改变Model或View,或者同时改变两者。只要Controller改变了Models的数据或者属性,所有依赖的View都会自动更新。
MVC模式能使界面(Viwe)和数据(Model)能有效的分开,由控制器(Controller)去控制。
我们现在以一个比较简单的电子时钟的例子来看看如何使用MVC模式来架构我们的程序.
首先我们来看一下Model,Model按照我的理解是数据,就是所有的共用数据都是存储在Model里面的,时钟里有这样的数据,小时,分钟,秒;现在我们来建立一个Model,ModelLocator.as:
// ModelLocator.as package net.smilecn.clock.model{ import flash.events.EventDispatcher; import flash.events.Event; // 需要用dispatchEvent发消息出去 public class ModelLocator extends EventDispatcher{ private var _hour:String; private var _minutes:String; private var _second:String; public function ModelLocator():void{ } public function get hour():String{ return _hour; } public function set hour(value:String):void{ _hour = value; dispatchEvent(new Event("changeHour")); } public function get minutes():String{ return _minutes; } public function set minutes(value:String):void{ _minutes = value; dispatchEvent(new Event("changeMinutes")); } public function get second():String{ return _second; } public function set second(value:String):void{ _second = value; dispatchEvent(new Event("changeSecond")); } } }
// Controller.as package net.smilecn.clock.control{ import flash.utils.Timer; import flash.events.TimerEvent; import net.smilecn.clock.model.ModelLocator; public class Controller{ private var _model:ModelLocator; private var _timer:Timer; public function Controller(model:ModelLocator):void{ _model = model; } public function startTime():void{ _timer = new Timer(1000,0); _timer.addEventListener(TimerEvent.TIMER,timerHandler); _timer.start(); } private function timerHandler(event:TimerEvent):void{ var nowDate:Date = new Date(); _model.hour = nowDate.getHours()>9?String(nowDate.getHours()):"0"+nowDate.getHours(); _model.minutes = nowDate.getMinutes()>9?String(nowDate.getMinutes()):"0"+nowDate.getMinutes(); _model.second = nowDate.getSeconds()>9?String(nowDate.getSeconds()):"0"+nowDate.getSeconds(); } } }
这个类中我们用到了Timer类,因为我们用的是时钟,所以需要一个定时器,Timer是一个很好的定时器,Timer(1000,0),这里1000是指1000毫秒,就是1秒钟触发一次定时钟,0表示次数,这里0是无限次,如果是大于0的数就是这个数的次数。侦听TimerEvent.TIMER事件就是1秒钟去执行一次timerHandler方法,timerHandler方法的功能是得到当前的时间然后去改变_model里面的值,再看一下ModelLocator.as里面的代码,当hour,minutes,second的值改变的时候就会去发消息出去,那么谁来侦听这些消息呢,当然是View,现在来看下View.as:
// View.as package net.smilecn.clock.view{ import flash.display.Sprite; import flash.events.Event; import flash.text.TextField; import net.smilecn.clock.model.ModelLocator; import net.smilecn.clock.control.Controller; public class View extends Sprite{ private var _model:ModelLocator; private var _controller:Controller; private var time_txt:TextField; public function View(model:ModelLocator,controller:Controller):void{ _model = model; _controller = controller; time_txt = new TextField(); addChild(time_txt); _model.addEventListener("changeHour",changeTimeHandler); _model.addEventListener("changeMinutes",changeTimeHandler); _model.addEventListener("changeSecond",changeTimeHandler); _controller.startTime(); } private function changeTimeHandler(event:Event):void{ time_txt.text = _model.hour+" : "+_model.minutes+" : "+_model.second; } } }
在View里面,侦听了_model的事件,所以当收到数据改变的消息后,将_model的数据显示到文本框中。
要使程序运行,我们现加一个文档类:
package net.smilecn.clock{ import flash.display.Sprite; import net.smilecn.clock.model.ModelLocator; import net.smilecn.clock.control.Controller; import net.smilecn.clock.view.View; public class Clock extends Sprite{ private var _model:ModelLocator; private var _controller:Controller; private var _view:View; public function Clock():void{ _model = new ModelLocator(); _controller = new Controller(_model); _view = new View(_model,_controller); addChild(_view); } } }
在文档类中建立了ModelLocator、Controller、View的实例,ModelLocator产生的实例被传到了Controller和View中,这样就保证了Controller和View使用是相同的ModelLocator,其实要达到这种效果不用这种方法也可以,可以用到上一节中用到的单例模式。
这里作一个总结,Controller是一个控制者,它去改变ModelLocator,ModelLocator的数据被改变后去更新View,使我们能看到数据。如果界面上有一些按钮交互,那么就应该是Controller去响应View里的按钮交互,响应后去通过一些操作后改变ModelLocator,ModelLocator数据改变后通知View去改变界面。
有人可以会说这个程序用更少的代码就可以完成,但这里只是演示程序的架构,当程序很大时,好的架构会使程序更清晰。
转载:http://blog.csdn.net/arrowyoung/archive/2008/03/13/2178384.aspx
-----------------------------------
做过Flash动画的Flash爱好者们都知道,要做好一个Flash动画,AS是必不可少的,即使只是很简单的几句代码也能起到整个Flash画龙点睛的作用。这里我只简单的介绍一下AS的基本常识。
首先我们要了解AS要写在什么地方,什么时候AS会被触发执行。
1、帧:
写在关键帧上面的AS,当时间轴上的指针走到这个关键帧的时候,就写在这个帧上面的AS就被触发执行了。常见的例子有在影片结尾的帧写上 stop() 等。操作方法就是点选关键帧,然后打开AS面板。
2、按钮:
不同于帧上面的AS,按钮上面的AS是要有触发条件的。要把AS写在按钮上,操作方法是点选目标按钮,然后打开AS面板。举个例子能说的更明白。
假设有一个动画,要让它在播放完同时停止,那么,你要做的就是在这个动画的最后一帧写AS
stop();
再假设有个按钮,效果是按下按钮后停止播放,那么步骤如下。
做一个按钮,放到主场景,点选按钮,然后打开AS面板。现在如果也在按钮上写
stop();
那么,输出的时候就会提示错误。正确的应该这样写
on(release){
stop();
}
这里要比帧的动画多这些代码: on(release){} , 整个代码翻译过来就是:
当(松开){
停止
}
红色的代码表示鼠标的触发事件事件之一,这里用的是 release 松开,按钮的常用事件:
release 松开
releaseOutside 在按钮外面松开
press 按下
rollOver 鼠标进入按钮的感应区
rollOut 鼠标离开按钮的感应区
现在很明确了:写在按钮上面的AS一定就是这种格式的:
on(事件){要执行的代码}
3、MC(电影剪辑)
如果你看懂了上面的内容,那么写在MC上面的AS和写在按钮上的大同小异。操作方法就是点选MC,然后打开AS面板。看个例子
onClipEvent(load){
stop();
}
同样,MC需要一个事件来触发AS的执行。翻译这段代码就是
当剪辑(载入){
停止
}
红色代码同样表示一个事件。MC的事件有下面这些:
load 载入,当MC出现的时候执行。也就是除非卸载这个MC,否则load事件内的代码只执行一次
unload 卸载,当MC卸载的时候执行
enterFrame 存在的每个帧。在MC存在的每个帧都要执行一次代码。如果你的场景有100个帧,有个MC从41帧开始出现到100帧才消失,那么这个MC上面的代码执行了60次
mouseDown 按下鼠标,在场景内任何地方都算。和按钮不一样的地方
mouseMove 移动鼠标,只要移动鼠标就执行代码
mouseUp 松开鼠标
同样你要明确:写在MC上的代码一定总是这种格式:
onClipEvent(事件){代码}
FLASH中常用语法关键字及语句(不断更新ing)
1、指令语句:
break 跳出最近的循环体(do...while,while...,for...,for(in)...)
continue 用在循环体内,表示忽略之后的语句,直接进入下一轮循环
#include "filename" 引入一个外部脚本文件:
var variable 定义一个局部变量(只在函数体内有效)
return [expression] 跳出函数体(并返回一个值)
new func(...) 新建一个对象,并用func构造函数进行构造
delete variable 删除一个变量,使其变为未定义
2、判断语句({}内语句数为1时{}可省):
if (expression1) {
statement(s)1
} else if (expression2) {
statement(s)2
...
} else {
statement(s)n
}
当expression1为true时执行statement(s)1,当expression2为true执行
statement(s)2……否则执行statement(s)n。{}内语句数为1时{}可省。
ifFrameLoaded ([scene,] frame) {
statement(s)
}
当场景scene的帧frame已经载入时,执行statement(s)。
3、循环语句({}内语句数为1时{}可省):
while (expression) {
statement(s)
}
当expression的值为true时反复执行statement(s)直到expression的值为false。
do {
statement(s)
} while (expression)
反复执行statement(s)直到expression为false。{}内语句数为1时{}可省。
for (statement1; expression; statement2) {
statements(s)
}
先执行statement1,当expression的值为true时反复执行statement(s),并在执行
完一轮后执行一次statement2,直到expression的值为false。
for (variable in obj_mc) {
statements(s)
}
variable依次取obj_mc的各成员名称,反复执行statements(s),直到所有成员都
取过一遍。
4、对象操作语句({}内语句数为1时{}可省):
with (obj_mc) {
statement(s)
}
对obj_mc进行操作,凡statement(s)里用到的与obj_mc的成员名相同的变量、函数
、影片片段,都指代obj_mc的成员。
tellTarget (mc) {
statement(s)
}
对mc进行操作,凡用到的变量、函数、影片片段,只要未指明绝对路径,都指代mc
的成员。
5、函数及事件:
function func(variable1, variable2, ...) {
statement(s)
}
定义一个函数。函数体内this对象指代调用该函数的对象或影片片段,未用var定义
的变量(非形参)从属于该函数所在的影片片段。func名称省略时该复合语句返回
一个类型为"function"的值,用以指代该函数。
on (mouseEvent) {
statement(s)
}
只能用在按钮的动作里。mouseEvent的可取值为:
press 鼠标键在按钮上按下
release 鼠标键在按钮上松开
releaseOutside 鼠标键在按钮区域外松开
rollOver 鼠标滑过按钮
rollOut 鼠标滑出按钮
dragOver 鼠标有键按下时滑过按钮
dragOut 鼠标有键按下时滑出按钮
keyPress(key) key键被按下,key为ASCII码字符或Key对象常量
各事件可用逗号分隔,当有一事件成立时就执行statement(s)。
onClipEvent (clipEvent) {
statement(s)
}
只能用在影片片段的动作里。clipEvent的可取值为:
load 该影片片段已载入
unload 该影片片段被卸载
data 用loadVariableNum载入数据后或用loadMovie载入影片的每个影片片段后
enterFrame 播放至该影片片段所在帧(若停在该帧则反复执行)
mouseMove 鼠标移动
mouseDown 鼠标键按下
mouseUp 鼠标键松开
keyDown 键盘键按下
keyUp 键盘键松开
各事件可用逗号分隔,当有一事件成立时就执行statement(s)。
flash中的常量及全局函数
1、常量:
true 逻辑真。
false 逻辑假。
null 空值,可与未定义值相等(但类型不同)。如variable未定义时,
variable == null为true。
NaN 表示Not a Number,即非数值量。用于表征数值计算时发生的非数值型错
误。如:1 * 'a'就得NaN。
newline 表示换行符,即'\n'。
Infinite 表示无穷大数值。如:-1 / 0得-Infinite。
2、数值运算函数:
= Number(expression)
将expression转化成数值,expression为false、null或未定义时返回0,
为true时返回1,无法转化时返回NaN。如:Number("12e2")返回1200。
= Boolean(expression)
将expression转化成布尔值。expression的值为false、null、"false"或
为字符串且Number(expression)为NaN或0则返回false,否则返回true。
= int(expression)
将expression转化成数值后取整。如:int("-1.2")返回-1。
= random(num)
随机返回0到num-1(num必须正整数)的某一个整数。
= isFinite(expression)
判断expression转化成数值后是否为有限量。比如isFinite(1/0)返回
false。
= isNaN(expression)
判断expression是否为非数值量。
= parseInt(expression, num)
把expression先转化为字符串后再按num进制理解转化为整数。比如:
parseInt(12, 16)返回18。
= parseFloat(string)
把字符串转化为浮点数。如:parseFloat("1.2e-2")返回0.012。
3、字符串运算函数:
= String(expression)
将expression转为字符串。expression的值可为布尔值、数值、一般对象
(返回"[object][object]")、数组对象(返回各项的值列表)、影片片
段(返回绝对路径)。
= chr(num)
返回ASCII码值为num的对应字符。
= ord(char)
返回字符char所对应的ASCII码值(8-bit)。
= length(string)
返回string长度(即字符个数)。
= substring(string, start_num, length_num)
返回string中第start_num(需>=0,否则取0)个字符开始,长度为
length_num(需>=0,否则忽略)的子串。若length省略或过界,则返回
start_num之后的整个子串。
= mbchr(num)
返回ASCII码值为num的对应双字节字符。
= mbord(char)
返回双字节字符char所对应的ASCII码值(16-bit)。
= mblength(string)
返回string的双字节长度。
= mbsubstring(string, start_num, length_num)
返回string中第start_num个字符开始,长度为length_num的子串。
= escape(string)
将一般字符串译成URL编码格式的字符串。如escape("1&2")返回"1%262"。
= unescape(string)
将URL格式的字符串解码成一般字符串。如unexcape("%D7%D4%D4%DA")返
回"自在"。
注:字符串按双字节字符处理时,双字节字符(如中文字符)代表一个整体。比如
字符串"I'm 自在幻想",用在length函数时返回12,而用在mblength函数时返回8。
4、其他函数:
= getProperty(mc, property)
返回影片片段mc的property属性值。
= targetPath(mc)
返回影片片段mc的绝对路径字符串。如主场景下的一个影片片段名为mc1,
则targetPath(_root.mc1)返回"_level0.mc1"。
= eval(target)
返回目标路径字符串target所指代的变量、对象或影片片段实例。如上例
中eval("_root.mc1")返回影片片段mc1实体。
= getTimer()
返回影片从开始播放到当前的时间间隔(毫秒单位)。
= getVersion()
返回系统平台及FlashPlayer的版本。如返回"WIN 5, 0, 30, 0"表示当前
系统为Windows,FlashPlayer的版本为5.0r30。