您的位置:首页 > Web前端 > JavaScript

JavaScript 的 MVC 模式

2012-12-18 22:49 267 查看
原文:Model-View-Controller(MVC)withJavaScript

作者:Alex@Net

译文:JavaScript的MVC模式

译者:justjavac

本文介绍了模型-视图-控制器模式在JavaScript中的实现。

我喜欢JavaScript,因为它是在世界上最灵活的语言之一。在JavaScript中,程序员可以根据自己的口味选择编程风格:面向过程或面向对象。如果你是一个重口味,JavaScript一样可以应付自如:面向过程,面向对象,面向方面,
使用JavaScript开发人员甚至可以使用函数式编程技术。

这篇文章中,我的目标是编写一个简单的JavaScript组件,来向大家展示一下JavaScript的强大。该组件是一个可编辑的项目列表(HTML中的select标签):用户可以选择某一项并删除它,或者添加新的项目到列表中。组件将由三个类构成,分别对应着MVC
设计模式的模型-视图-控制器。

这篇文章只是一个简单的指导。如果你希望在实际的项目中使用它,你需要进行适当的修改。我相信你拥有创建和运行JavaScript程序的一切:大脑,双手,文本编辑器(如记事本),浏览器(例如我的最爱Chrome)。

既然我们的代码要使用MVC模式,因此我在这里简单介绍一个这个设计模式。MVC模式的英文名称是Model-View-Controllerpattern,顾名思义,其主要部分组成:

模型Model(),用于存储程序中使用到的数据;
视图(View),用不同的表现形式来呈现数据;
控制器(Controller),更新模型。

在维基百科对MVC体系结构的定义中,它由如下三部分组成:

模型(Model)-“数据模型”(Model)用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。“模型”有对数据直接访问的权力。“模型”不依赖“视图”和“控制器”,也就是说,模型不关心它会被如何显示或是如何被操作。

视图(View)-视图层能够实现数据有目的的显示,通常是一个用户界面元素。在视图中一般没有程序上的逻辑。在Web应用程序中的MVC,通常把显示动态数据的html页面称为视图。

控制器(Controller)-处理和响应事件,通常是用户操作,并监控模型上的变化,然后去修改视图。

Thedataofthecomponentisalistofitems,inwhichoneparticularitemcanbeselectedanddeleted.So,themodelofthecomponentisverysimple-itisstoredinanarraypropertyandselecteditemproperty;andhereitis:

我们将基于MVC实现一个数据列表组件,列表中的项目可以被选择和删除。因此,组件模型是非常简单的-它只需要两个属性:



数组_items用来存储所有元素
普通变量_selectedIndex用来存储选定的元素索引

代码如下:

01
/**
02
*
模型。
03
*
04
*
模型存储所有元素,并在状态变更时通知观察者(Observer)。
05
*/
06
function
ListModel(items)
{
07
this
._items
=items;
//
所有元素
08
this
._selectedIndex
=-1;
//
被选择元素的索引
09
10
this
.itemAdded
=
new
Event(
this
);
11
this
.itemRemoved
=
new
Event(
this
);
12
this
.selectedIndexChanged
=
new
Event(
this
);
13
}
14
15
ListModel.prototype
={
16
getItems
:
function
()
{
17
return
[].concat(
this
._items);
18
},
19
20
addItem
:
function
(item)
{
21
this
._items.push(item);
22
this
.itemAdded.notify({item
:item});
23
},
24
25
removeItemAt
:
function
(index)
{
26
var
item;
27
28
item
=
this
._items[index];
29
this
._items.splice(index,
1);
30
this
.itemRemoved.notify({item
:item});
31
32
if
(index
===
this
._selectedIndex)
{
33
this
.setSelectedIndex(-1);
34
}
35
},
36
37
getSelectedIndex
:
function
()
{
38
return
this
._selectedIndex;
39
},
40
41
setSelectedIndex
:
function
(index)
{
42
var
previousIndex;
43
44
previousIndex
=
this
._selectedIndex;
45
this
._selectedIndex
=index;
46
this
.selectedIndexChanged.notify({previous
:previousIndex});
47
}
48
};
Event是一个简单的实现了观察者模式(Observerpattern)的类:

01
function
Event(sender)
{
02
this
._sender
=sender;
03
this
._listeners
=[];
04
}
05
06
Event.prototype
={
07
attach
:
function
(listener)
{
08
this
._listeners.push(listener);
09
},
10
11
notify
:
function
(args)
{
12
var
index;
13
14
for
(index
=0;index<
this
._listeners.length;
index+=1){
15
this
._listeners[index](
this
._sender,
args);
16
}
17
}
18
};
View类需要定义控制器类,以便与它交互。虽然这个任务可以有许多不同的接口(interface),但我更喜欢最简单的。我希望我的项目是在一个ListBox控件和它下面的两个按钮:“加号”按钮添加项目,“减”删除所选项目。组件所提供的“选择”功能则需要select控件的原生功能的支持。

一个View类被绑定在一个Controller类上,其中「…控制器处理用户输入事件,通常是通过一个已注册的回调函数」(wikipedia.org)。

下面是View和Controller类:

001
/**
002
*
视图。
003
*
004
*
视图显示模型数据,并触发UI事件。
005
*
控制器用来处理这些用户交互事件
006
*/
007
function
ListView(model,
elements){
008
this
._model
=model;
009
this
._elements
=elements;
010
011
this
.listModified
=
new
Event(
this
);
012
this
.addButtonClicked
=
new
Event(
this
);
013
this
.delButtonClicked
=
new
Event(
this
);
014
015
var
_this
=
this
;
016
017
//
绑定模型监听器
018
this
._model.itemAdded.attach(
function
()
{
019
_this.rebuildList();
020
});
021
022
this
._model.itemRemoved.attach(
function
()
{
023
_this.rebuildList();
024
});
025
026
//
将监听器绑定到HTML控件上
027
this
._elements.list.change(
function
(e)
{
028
_this.listModified.notify({
index:e.target.selectedIndex});
029
});
030
031
this
._elements.addButton.click(
function
()
{
032
_this.addButtonClicked.notify();
033
});
034
035
this
._elements.delButton.click(
function
()
{
036
_this.delButtonClicked.notify();
037
});
038
}
039
040
ListView.prototype
={
041
show
:
function
()
{
042
this
.rebuildList();
043
},
044
045
rebuildList
:
function
()
{
046
var
list,
items,key;
047
048
list
=
this
._elements.list;
049
list.html(
''
);
050
051
items
=
this
._model.getItems();
052
for
(key
in
items)
{
053
if
(items.hasOwnProperty(key))
{
054
list.append($(
'<option>'
+
items[key]+
'</option>'
));
055
}
056
}
057
058
this
._model.setSelectedIndex(-1);
059
}
060
};
061
062
/**
063
*
控制器。
064
*
065
*
控制器响应用户操作,调用模型上的变化函数。
066
*/
067
function
ListController(model,
view){
068
this
._model
=model;
069
this
._view
=view;
070
071
var
_this
=
this
;
072
073
this
._view.listModified.attach(
function
(sender,
args){
074
_this.updateSelected(args.index);
075
});
076
077
this
._view.addButtonClicked.attach(
function
()
{
078
_this.addItem();
079
});
080
081
this
._view.delButtonClicked.attach(
function
()
{
082
_this.delItem();
083
});
084
}
085
086
ListController.prototype
={
087
addItem
:
function
()
{
088
var
item
=window.prompt(
'Add
item:'
,
''
);
089
if
(item)
{
090
this
._model.addItem(item);
091
}
092
},
093
094
delItem
:
function
()
{
095
var
index;
096
097
index
=
this
._model.getSelectedIndex();
098
if
(index
!==-1){
099
this
._model.removeItemAt(
this
._model.getSelectedIndex());
100
}
101
},
102
103
updateSelected
:
function
(index)
{
104
this
._model.setSelectedIndex(index);
105
}
106
};
当然,Model,View,Controller类应当被实例化。

下面是一个使用此MVC的完整代码:

view
source

print?

01
$(
function
()
{
02
var
model
=
new
ListModel([
'PHP'
,
'JavaScript'
]),
03
04
view
=
new
ListView(model,
{
05
'list'
:
$(
'#list'
),
06
'addButton'
:
$(
'#plusBtn'
),
07
'delButton'
:
$(
'#minusBtn'
)
08
}),
09
10
controller
=
new
ListController(model,
view);
11
view.show();
12
});
13
14
<select
id=
"list"
size=
"10"
style=
"width:
15em"
></select><br/>
15
<button
id=
"plusBtn"
>
+</button>
16
<button
id=
"minusBtn"
>
-</button>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: