原文:Model-View-Controller (MVC) with JavaScript

作者:Alex@Net

译文:JavaScript 的 MVC 模式

译者:justjavac


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

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

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

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

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

  • 模型Model(),用于存储程序中使用到的数据;

  • 视图(View),用不同的表现形式来呈现数据;

  • 控制器(Controller),更新模型。

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

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

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

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

The data of the component is a list of items, in which one particular item can be selected and deleted. So, the model of the component is very simple - it is stored in an array property and selected item property; and here it is:

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

  1. 数组 _items 用来存储所有元素

  2. 普通变量 _selectedIndex 用来存储选定的元素索引

代码如下:

/*** 模型。** 模型存储所有元素,并在状态变更时通知观察者(Observer)。*/
function ListModel(items) {this._items = items;        // 所有元素this._selectedIndex = -1;   // 被选择元素的索引this.itemAdded = new Event(this);this.itemRemoved = new Event(this);this.selectedIndexChanged = new Event(this);
}ListModel.prototype = {getItems : function () {return [].concat(this._items);},addItem : function (item) {this._items.push(item);this.itemAdded.notify({item : item});},removeItemAt : function (index) {var item;item = this._items[index];this._items.splice(index, 1);this.itemRemoved.notify({item : item});if (index === this._selectedIndex) {this.setSelectedIndex(-1);}},getSelectedIndex : function () {return this._selectedIndex;},setSelectedIndex : function (index) {var previousIndex;previousIndex = this._selectedIndex;this._selectedIndex = index;this.selectedIndexChanged.notify({previous : previousIndex});}
};

Event 是一个简单的实现了观察者模式(Observer pattern)的类:

function Event(sender) {this._sender = sender;this._listeners = [];
}Event.prototype = {attach : function (listener) {this._listeners.push(listener);},notify : function (args) {var index;for (index = 0; index < this._listeners.length; index += 1) {this._listeners[index](this._sender, args);}}
};

View 类需要定义控制器类,以便与它交互。 虽然这个任务可以有许多不同的接口(interface),但我更喜欢最简单的。 我希望我的项目是在一个 ListBox 控件和它下面的两个按钮:“加号”按钮添加项目,“减”删除所选项目。 组件所提供的“选择”功能则需要 select 控件的原生功能的支持。

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

下面是 View 和 Controller 类:

/*** 视图。* * 视图显示模型数据,并触发 UI 事件。* 控制器用来处理这些用户交互事件*/
function ListView(model, elements) {this._model = model;this._elements = elements;this.listModified = new Event(this);this.addButtonClicked = new Event(this);this.delButtonClicked = new Event(this);var _this = this;// 绑定模型监听器this._model.itemAdded.attach(function () {_this.rebuildList();});this._model.itemRemoved.attach(function () {_this.rebuildList();});// 将监听器绑定到 HTML 控件上this._elements.list.change(function (e) {_this.listModified.notify({ index : e.target.selectedIndex });});this._elements.addButton.click(function () {_this.addButtonClicked.notify();});this._elements.delButton.click(function () {_this.delButtonClicked.notify();});
}ListView.prototype = {show : function () {this.rebuildList();},rebuildList : function () {var list, items, key;list = this._elements.list;list.html('');items = this._model.getItems();for (key in items) {if (items.hasOwnProperty(key)) {list.append($('<option>' + items[key] + '</option>'));}}this._model.setSelectedIndex(-1);}
};/*** 控制器。** 控制器响应用户操作,调用模型上的变化函数。*/
function ListController(model, view) {this._model = model;this._view = view;var _this = this;this._view.listModified.attach(function (sender, args) {_this.updateSelected(args.index);});this._view.addButtonClicked.attach(function () {_this.addItem();});this._view.delButtonClicked.attach(function () {_this.delItem();});
}ListController.prototype = {addItem : function () {var item = window.prompt('Add item:', '');if (item) {this._model.addItem(item);}},delItem : function () {var index;index = this._model.getSelectedIndex();if (index !== -1) {this._model.removeItemAt(this._model.getSelectedIndex());}},updateSelected : function (index) {this._model.setSelectedIndex(index);}
};

当然,ModelViewController 类应当被实例化。

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

$(function () {var model = new ListModel(['PHP', 'JavaScript']),view = new ListView(model, {'list' : $('#list'), 'addButton' : $('#plusBtn'), 'delButton' : $('#minusBtn')}),controller = new ListController(model, view);        view.show();
});<select id="list" size="10" style="width: 15em"></select><br/>
<button id="plusBtn">  +  </button>
<button id="minusBtn">  -  </button>

转载于:https://www.cnblogs.com/justjavac/archive/2013/01/08/model-view-controller-mvc-javascript.html

「译」JavaScript 的 MVC 模式相关推荐

  1. 变量、中文-「译」javascript 的 12 个怪癖(quirks)-by小雨

    在写这篇文章之前,xxx已经写过了几篇关于改变量.中文-主题的文章,想要懂得的朋友可以去翻一下之前的文章 原文:12 JavaScript quirks 译文:「译」javascript 的 12 个 ...

  2. 「译」javascript 中的 delete

    在这篇文章中作者从<JavaScript面向对象编程指南>一书中关于 delete 的错误讲起,详细讲述了关于 delete 操作的实现, 局限以及在不同浏览器和插件(这里指 firebu ...

  3. js最小化浏览器_「译」解析、抽象语法树(ast) +如何最小化解析时间的5个技巧...

    前言 该系列课程会在本周陆续更新完毕,主要讲解的都是工作中可能会遇到的真实开发中比较重要的问题以及相应的解决方法.通过本系列的课程学习,希望能对你日常的工作带来些许变化.当然,欢迎大家关注我,我将持续 ...

  4. 「译」一起探讨 JavaScript 的对象

    「译」一起探讨 JavaScript 的对象 原文地址:Let's explore objects in JavaScript 原文作者:Cristi Salcescu 译文出自:阿里云翻译小组 译文 ...

  5. iOS 9,为前端世界都带来了些什么?「译」

    2015 年 9 月,Apple 重磅发布了全新的 iPhone 6s/6s Plus.iPad Pro 与全新的操作系统 watchOS 2 与 tvOS 9(是的,这货居然是第 9 版),加上已经 ...

  6. jvm 系列(九):如何优化 Java GC 「译」

    本文由CrowHawk翻译,地址:如何优化Java GC「译」,是Java GC调优的经典佳作. Sangmin Lee发表在Cubrid上的"Become a Java GC Expert ...

  7. jvm系列(十):如何优化Java GC「译」

    本文由CrowHawk翻译,地址:如何优化Java GC「译」,是Java GC调优的经典佳作. Sangmin Lee发表在Cubrid上的"Become a Java GC Expert ...

  8. 「译」一个3D网页是如何制作的

    「译」一个3D网页是如何制作的 原文: 本文作者制作了一个3D网页作为自己的个人主页,是一个遥控汽车的游戏页面.页面十分有趣,感兴趣的朋友可以先打开体验一下. 以下为原文的译文,是我个人理解的版本.大 ...

  9. 「译」如何正确学习JavaScript

    原文地址: http://www.crimx.com/2014/05/15/how-to-learn-javascript-properly 原文:How to Learn JavaScript Pr ...

最新文章

  1. 机器之心公开演讲:如何用AI技术传播AI知识
  2. Machine Learning week 8 quiz: Principal Component Analysis
  3. 60v5g无刷电机矢量控制器_完成一个最小FOC矢量控制系统所需的基本模块和功能配置...
  4. c++检测ip是否匹配子网掩码_网络工程师从入门到精通通俗易懂系列 | ARP和IP这篇文章讲的相当详细了,这么基础的知识往往也是最容易遗忘的!...
  5. 父级div没高度不能自适应高度的原因——子级使用css float浮动
  6. r语言实现自相关分析和偏相关分析
  7. 白帽子讲web安全读后感2
  8. C++ primer 5th 读完的一点心得体会
  9. JQuery实现防抖节流
  10. iphone模拟器安装app
  11. 韩信点兵问题(C语言)
  12. 由frankmocap得到的.pkl文件转为.bvh或者.fbx
  13. 什么原因导致了儿童自闭症?跟父母养育有关吗?
  14. mysql数据库修改密码
  15. Bi-directional Cross-Modality Feature Propagation with Separation-and Aggregation Gate_eccv2020
  16. 这可能是全网最简单的KMP了
  17. 信息系统项目管理师必背核心考点(二十二)项目变更请求
  18. Prim 普里姆算法(邻接矩阵)C语言版
  19. ubuntu18 、20中文输入法安装
  20. 串联分压电路mos防反接电路

热门文章

  1. Centos查看已经安装的软件或者包
  2. 德鲁伊druid数据库明文密码加密
  3. mybatis if标签字符串判断
  4. 工具箱锁打不开了怎么办_锁芯坏了门打不开怎么办?锁芯拆开的方法是什么?...
  5. 【CSP201312-3】最大的矩形,单调栈
  6. 【NOIP1999】【codevs1083】Cantor表(找规律)
  7. 【NOIP2004】【Luogu1085】不高兴的津津
  8. android同步方法和对象的区别是什么,(4.1.10.8)Android Handler之同步屏障机制(sync barrier)...
  9. Python入门--模块,from,import,自定义模块
  10. 分治法——查找问题 —— 寻找一个序列中第k小的元素和查找最大和次大元素