【MVC学习笔记01】初窥奥秘
前言
最近工作落实了,是我非常喜欢的无线前端,会接触很多新东西啦,需要努力才行。因为会用到backbone,所以要学习MVC啦。
MVC(模型-视图-控制器),这种模式最早被用于构建桌面程序和服务器端的应用程序。
最近几年由于前后端数据的转移,前端所占的业务逻辑越来越重,于是这种模式便出现在了我们前端的javascript中了,比如Backbone 然后MVP与MVVM也先后在前端出现,并且各自拥有其拥戴者。
初探MVC
MVC是一种架构设计模式,他通过关注点分离改进程序组织,从而达到优化程序的目的。
MVC强制将业务数据(model)与用户界面(view)分离,controller用以管理用户输入以及一些逻辑。 MVC其实也是经过了一些发展的:
model代表特定于领域的数据,他完全不知道什么是view或者controller,但是当model发生改变时,他会通知他的view(观察者)
view描述的是model的当前状态,观察者模式用于让view了解model什么时候发生了变化
presentation由view关注,但不只是单个view和controller,屏幕上每个部分或者元素都需要做到view-controller对应
controller在view-controller对中的作用是处理用户交互(点击、滑动等动作),为view做决定。
由此我们可以察觉,发布/订阅(publish/subscribe)(观察者模式)好像和我们的MVC有一定渊源,于是我们来简单的看一下观察者模式。
Publish/Subscribe(发布/订阅)模式
在javascript中,我们一般使用Publish/Subscribe(发布/订阅)模式。

Publish/Subscribe模式使用了一个主题/事件通道,这个通道介于希望接收到通知(订阅者)的对象和激活事件的对象(发布者)之间。
该事件系统允许代码定义应用程序的特定事件,事件可传递参数,参数包含订阅者需要的值,这样避免了订阅者与发布者之间产生依赖。
他允许任何订阅者执行适当的事件处理程序来注册和接收发布者发出的通知。
我们这里假设我们已经实现了publish、subscribe、unsubscribe方法,这里来实现一个简单的mail处理程序:
//接收消息数量
var mailCounter = 0;
//初始化订阅、名称是inbox/newMessage //呈现消息预览
var subscriber1 = subscribe('inbox/newMessage', function (topic, data) {
alert('a new message:', topic);
//使用从目标subject传递过来的data,呈现消息
$('#sender').html(data.sender);
$('#content').html(data.body);
}); //另外一个订阅者,使用同样的data,但是干了不同的事情(更新接收消息数量)
var subscriber2 = subscribe('inbox/newMessage', function (topic, data) {
$('#newMessageCounter').html(mailCounter++);
}); //发布消息啦!
publish('inbox/newMessage', [{
sender: '叶小钗',
body: '一起来看霹雳布袋戏吧!!!'
}]); //可以取消订阅
// unsubscribe(subscriber1);
// unsubscribe(subscriber2);
这段代码的中心是促进松散耦合,通过订阅另一个对象的特定任务或活动,当任务/活动发生时获得通知,而不是单个对象直接调用其他对象的方法。
我们使用Publish/Subscribe模式的好处就是分解应用程序,松散耦合的块,改进代码管理。
这种模式其实也有一个问题,就相当于领导发命令下面的士兵不一定能完成任务,他缺少一个跟踪机制,订阅者和发布者之间会相互无视。
Publish/Subscribe非常适用与javascript生态系统,因为ECMAScript是由事件驱动的,在浏览器下尤其如此,DOM将事件作为脚本编程的主要交互API,所以在代码实现中,无论ECMAscript还是dom都不会提供核心对象或方法来创建自定义事件系统(DOM3除外)。
但是很多类库帮我们实现了Publish/Subscribe系统(jquery) $('dom').trigger('channel', data);
javascript实现Publish/Subscribe
var pubsub = {};
(function (q) {
var topics = {},
subUid = -1;
//发布或者广播事件
q.publish = function (topic, args) {
if (!topics[topic]) {
return false;
}
var subscribers = topics[topic],
len = subscribers ? subscribers.length : 0;
while (len--) {
subscribers[len].func(topic, args);
}
return false;
};
//通过特定的名称和回调函数订阅事件,topic/event触发时执行事件
q.subscribe = function (topic, func) {
if (!topics[topic]) {
topics[topic] = [];
}
var token = (++subUid).toString();
topics[topic].push({
token: token,
func: func
});
return token;
};
q.unsubscribe = function (token) {
for (var m in topics) {
if (topics[m]) {
for (var i = 0, len = topics[m].length; i < len; i++) {
if (topics[m][i].token === token) {
topics[m].splice(i, 1);
return token;
}
}
}
}
return this;
};
})(pubsub);
//简单的消息处理程序
//记录所有通过订阅者接收到的主题和数据
var messageLogger = function (topics, data) {
//do something
console.log(topics + ' ' + data);
};
//订阅者监听订阅的topic,一旦该topic广播一个通知,订阅者就调用回调函数
var subscription = pubsub.subscribe('inbox/newMessage', messageLogger);
//发布者发布消息
pubsub.publish('inbox/newMessage', '刀狂剑痴叶小钗');
pubsub.publish('inbox/newMessage', {
id: '叶小钗',
name: '刀狂剑痴'
});
因为,这个不是今天的重点,我们暂时写到这吧,回过头继续看我们的MVC。
再探MVC
MVC由三个核心组件组成。
model
model管理应用程序的数据,model不涉及用户界面,也不涉及表示层,他是应用程序可能需要的特殊形式的数据。
当model改变时,他会通知他的观察者(view),view就会做出相应的改变达到同步的效果。
假如我们有一个javascript图片库应用程序,在图片库中,一个图片就是一个model,他便是一个独特的数据。
这个model可以包含标题,图像源等信息 { src: '1.jpg', title: '叶小钗', viewed: false }
View
视图是model的可视化表示,表示当前状态的筛选视图,一个视图通常检测一个model(模型),并在model更改时进行通知,使view本身能够更新。
View通常是“愚钝”的,因为他对应用程序中的View与Controller了解非常有限。
用户一般与View发生交互,包括读取编辑model,我们通过操作view来编辑器元数据,更新model的实际任务是在controller上进行的。
我们下面来看一个例子:
我们在view内定义一个render方法,他负责使用javascript模板引擎渲染model的内容,并产生更新操作(还是图片相关的操作),然后model将render回调作为一个订阅者加进去,以便model改变时触发view更新
var bulidPhotoView = function (photoModel, photoController) {
var base = $('<div/>'),
photoEl = $('<div/>');
base.append(photoEl);
var render = function () {
//__template模板方法并不存在其功能为获取id标志的html模板与model生成实体html
photoEl.html(__template('id', photoModel));
};
photoModel.addSubscriber(render);
photoEl.delegate('click', function () {
photoController.handleEvent('click', photoModel);
});
var show = function () {
photoEl.show();
};
var hide = function () {
photoEl.hide();
};
return { showView: show, hideView: hide };
}
Controller
controller是model与view之间的中介,当用户操作view时,controller负责更新model。
View将委托给controller进行操作,当view觉得合适时,view也会委托controller处理model的事件。
这里有点绕,因为我们javascript中的MVC与经典的有点不一样。
比如backbone的框架,他包含Model模型和View视图,但是他其实并不包含Controller,其视图和路由行为与controller有点类似,但是他们都不是controller。
【阶段总结】
MVC关注分离,他有利于简化应用程序功能的模块化,从而带来了这些好处:
① 整体维护变得简单,数据是否改变,什么时候改变我们可以追踪,不论是model或者controller最终都会体现在view上
② 解耦model与view
③ model与controller代码的重复被消除了。
结语
我们今天一起学习了MVC,我对这块的理解还很浅,因为最近会用到backbone,所以感觉自己应该对这块知识有所掌握。
接下来我们一起来学习下吧,希望这次学习后对MVC的理解能够加深一点。
【MVC学习笔记01】初窥奥秘的更多相关文章
- STM32学习笔记之一(初窥STM32)
怎么做好学习笔记? 答:自我感知-->学习知识-->归纳总结-->自我升华(真正属于自己的知识是,抛开书本,运用时,你还能记得的思想) 自我感知--看到知识概念,先自我感觉那应该是个 ...
- MVC学习笔记-01
什么是MVC MVC是指(Model-View-Controll即模型-视图-控制器)用于表示表示一种软件架构模式,它把软件分成三个基本的部分:模型(Model),视图(view),控制器(Contr ...
- Spring MVC学习笔记 01
applicationcontext.xml的配置 <?xml version="1.0" encoding="UTF-8" ?> <bean ...
- Spring MVC 学习笔记一 HelloWorld
Spring MVC 学习笔记一 HelloWorld Spring MVC 的使用可以按照以下步骤进行(使用Eclipse): 加入JAR包 在web.xml中配置DispatcherServlet ...
- Spring MVC 学习笔记9 —— 实现简单的用户管理(4)用户登录显示局部异常信息
Spring MVC 学习笔记9 -- 实现简单的用户管理(4.2)用户登录--显示局部异常信息 第二部分:显示局部异常信息,而不是500错误页 1. 写一个方法,把UserException传进来. ...
- Spring MVC 学习笔记8 —— 实现简单的用户管理(4)用户登录
Spring MVC 学习笔记8 -- 实现简单的用户管理(4)用户登录 增删改查,login 1. login.jsp,写在外面,及跟WEB-INF同一级目录,如:ls Webcontent; &g ...
- 软件测试之loadrunner学习笔记-01事务
loadrunner学习笔记-01事务<转载至网络> 事务又称为Transaction,事务是一个点为了衡量某个action的性能,需要在开始和结束位置插入一个范围,定义这样一个事务. 作 ...
- MVC学习笔记索引帖
[MVC学习笔记]1.项目结构搭建及单个类在各个层次中的实现 [MVC学习笔记]2.使用T4模板生成其他类的具体实现 [MVC学习笔记]3.使用Spring.Net应用IOC(依赖倒置) [MVC学习 ...
- ASP.NET MVC学习笔记-----Filter2
ASP.NET MVC学习笔记-----Filter(2) 接上篇ASP.NET MVC学习笔记-----Filter(1) Action Filter Action Filter可以基于任何目的使用 ...
随机推荐
- Razor基本语法
前言: Razor引擎的核心是识别@符号及尖括号: 1.<...></...> 2.<.../> [之所以说是"尖括号"而非& ...
- 同级、父子级div定位
以两个div右上角对齐为例: 效果图: 1.同级定位 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&quo ...
- JS魔法堂:jQuery.Deferred(jQuery1.5-2.1)源码剖析
一.前言 jQuery.Deferred作为1.5的新特性出现在jQuery上,而jQuery.ajax函数也做了相应的调整.因此我们能如下的使用xhr请求调用,并实现事件处理函数晚绑定. var p ...
- qt 窗口动画
窗口动画 编辑删除转载 2015-10-10 14:50:27 标签:qt渐变动画 一个应用程序通常包含多个动画,例如,你可能希望同时移动许多graphic items或者一个个按照串行的方式的移动他 ...
- 解决未能加载文件或程序集'WebGrease‘的问题
在多个视图中,如果有使用共用的样式代码,可以把它们移至CSS文件中去.今天Insus.NET就举例一个例子来说明.比如前2篇中<ASP.NET MVC图片管理(上传,预览与显示)>http ...
- 【FTP】在自己的电脑上建立FTP服务器
<1> 添加新用户: “计算机”点击右键 “管理”得到: 点击“本地用户和组”,点击“用户”: 右键 “新用户”: 设定用户名与密码,这是以后连FTP服务器时用的登录用户名与密码. < ...
- Entity Framework 实体框架的形成之旅--Code First的框架设计(5)
在前面几篇介绍了Entity Framework 实体框架的形成过程,整体框架主要是基于Database First的方式构建,也就是利用EDMX文件的映射关系,构建表与表之间的关系,这种模式弹性好, ...
- 从C#到Objective-C,循序渐进学习苹果开发(3)--分类(category)和协议Protocal的理解
本随笔系列主要介绍从一个Windows平台从事C#开发到Mac平台苹果开发的一系列感想和体验历程,本系列文章是在起步阶段逐步积累的,希望带给大家更好,更真实的转换历程体验.本文继续上一篇随笔<从 ...
- oracle 查询周的第一天日期
项目的开发中需要用到一个查询周的第一天日期的函数 搜索N久很难找到解决的方法 只要自己写一个先用着 代码如下 a_week格式为 'YYYYIW' 如 '200801'表示2008年的第一周 周使用I ...
- Unicode中文和特殊字符的编码范围
编程中有时候需要用到匹配中文的正则,一般用 [ \u4e00-\u9fa5]+ 即可搞定.不过这正则对一般的火星文鸟语就不太适用了,甚至全角的标点符号都不包含在内.例如游戏里面的玩家名,普通青年一般都 ...