前端 MV*模式
https://github.com/livoras/blog/issues/11
MVC

调用关系如下:
Controller(model) ,controller中执行业务逻辑,操作model
View(controller,model),view中绑定dom的交互事件,回调函数中调用controller的方法;接着对model进行监视,设置对应的回调方法(model.on(xx,()=>{ 此处更新dom }))
Model(),当自身数据被修改时,自身发出对应事件(this.trigger(xx))。
特点:代码的执行次序依次 View -> Controller -> Model -> View
优点:
1.模块分化明显,易于管理。Controller集中了业务逻辑、View集中了dom操作
缺点:
1.单元测试困难。测试controller,修改了model,view中事件回调修改dom,被修改的视图难以检测正确性
2.混乱的数据流(多个model与多个view交错调用)。即由于 Model 对外直接暴露了 set 和 on 方法,导致 View 层可以随意改变Model中的值,也可以随意监听 Model中值的变化。这样的设定最终会导致一个庞大的 Model中某个字段变化后,可能触发无数个 change 事件,在这些 change 事件的回调中,可能还有新的 set方法调用,导致更多的 change 事件触发,更糟糕的是,一个 Model 还能改变另一个 Model 的值,整个数据流动的方式变得更加混乱,不可捉摸(这里参考自《深入React技术栈》P193中对MVC的解释,感觉和本文对MVC的解释不一致,model的set方法本在本文应该是在controller中调用,而不是给view直接调用的)
3.页面更新逻辑复杂(多个局部更新导致页面整体逻辑复杂)。一个页面中有多个view,都有自己独立的渲染操作,支持独立更新,这种独立更新正是高效率的关键(当前页面的状态是由多个view的更新界面函数所决定的),但会导致整个页面的更新逻辑复杂,难以定位问题
对于2、3点的解决方案:把多个局部更新替换一个整体更新,及每次更新数据,就读取所有数据,重新渲染整个页面,这导致效率低下,但数据流动清晰,逻辑简单。
以上过程中,trigger和on的观察者api可以这么实现:
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
// 方式1:使用jquery
var model = $({});
model.on('xx',function(evt,val){
console.log('xx happened ' + val)
});
model.trigger('xx',1); // 方式2:自定义
function Model(){
var evts = {};
this.on = function(evtName,cb){
evts[evtName] = evts[evtName] || [];
evts[evtName].push(cb);
};
this.trigger = function(evtName){
var cbs = evts[evtName] || [];
var evt = {};
var vals = [evt];
vals = vals.concat([].splice.call(arguments,1));
cbs.forEach(function(cb){
cb.apply(null,vals)
})
}
}
model = new Model();
model.on('xx',function(evt,val){
console.log('xx happened ' + val)
});
model.trigger('xx',1); // 方式3:使用node EventEmitter
</script>
MVP
和mvc的区别在于,对model的监听和更新dom(model.on(xx,()=>{ 更新dom })) 从view中移动到presenter。
调用关系如下:
View(presenter),绑定dom交互事件,调用presenter中的业务逻辑,设置对外的更新ui的接口
Presenter(view,model),执行业务逻辑,更新model,在model的监听事件中,调用view的接口,来修改view
Model(),和mvc一致
特点:代码的执行次序依次是 view -> presenter -> model -> presenter -> view
优点:
易于测试。把对model的监听和更新dom的操作移动到了presenter中,测试的时候仅仅需要关注presenter中的逻辑即可,因为对于view,这里仅仅是调用了那一块的接口,所以不需要对那边担心。
view便于组件化。写好对外的更新ui的接口,以及在交互事件中调用presenter即可。
MVVM
是对mvp的改良。
MVVM的调用关系和MVP一样。但是,在ViewModel(Model of View)当中会有一个叫Binder,或者是Data-binding engine的东西。以前全部由Presenter负责的View和Model之间数据同步操作交由给Binder处理。
ViewModel = Presenter + Binder
在界面(或者是view的模板里)中声明好view与model的绑定关系,binder去读取这个关系,并做好记录,内部完成双向绑定的功能。即Presenter中对model进行修改,Binder自动去修改对应的ui,ui上发生变化(input输入),Binder自动把数据更新到model上。
前端 MV*模式的更多相关文章
- MV*模式的个人理解
		
MV*模式主要解决的问题就是 View代码难以维护的问题. MV*模式将View中的逻辑分离出去,形成一个弱逻辑的易于维护的视图. MV*中的*是Model和View的桥梁,负责保持Model和Vie ...
 - 界面之下:还原真实的 MV* 模式
		
界面之下:还原真实的MV*模式 作者:戴嘉华 转载请注明出处并保留原文链接( https://github.com/livoras/blog/issues/11 )和作者信息. 目录: 前言 MVC ...
 - MV*模式
		
MV*模式 MVC框架最早出现在Java领域,然后慢慢在前端开发中也被提到,后来又出现了MVP,以及现在最成熟的MVVM. MVC model 数据模型 view 视图 controller 控制器 ...
 - 前端MV*框架的意义
		
经常有人质疑,在前端搞MV*有什么意义?也有人提出这样的疑问:以AngularJS,Knockout,BackBone为代表的MV*框架,它跟jQuery这样的框架有什么区别?我jQuery用得好好的 ...
 - 前端mv框架下(目前写的是vue),对组件抽象的思考
		
前沿: 抽象是门大学问.前端mv框架中,以组件化的概念为主.经常会考虑抽象到组件级别,进行复用.合理的抽象,能提高效率,减少业务逻辑视图的耦合程度.不合理的抽象,则会增加代码的复杂程度. 遇到的问题 ...
 - Spring MVC的前端控制器模式
		
前端控制器模式 spring mvc也是依赖servlet,所以spring mvc的请求处理是从一个servlet开始,这个servlet就是DispatcherServlet.前端控制器模式(Fr ...
 - 【整理总结】代码沉淀 - Caliburn.Micro - MV*模式短小精悍的框架
		
Caliburn.Micro - Xaml made easy. web: https://github.com/Caliburn-Micro/Caliburn.Microdocument: http ...
 - 前端架构模式 All In One
		
前端架构模式 All In One 架构模式 同构 异构 微前端 Web Components 组件化 无框架 去框架 前后端分离 前端架构图 Clean Architecture https://b ...
 - JavaScript之MV*模式
		
前言 在前端技术的快速发展过程中,MVC(模型-视图-控制器).MVP(模型-视图-表示器)和MVVM(模型-视图-视图模型)也得到了很多使用.然而,这三种框架模式非常相似,不易分清,易于混淆.本文重 ...
 
随机推荐
- C 语言实例 - 使用结构体(struct)
			
C 语言实例 - 使用结构体(struct) C 语言实例 C 语言实例 使用结构体(struct)存储学生信息. 实例 #include <stdio.h> struct student ...
 - 关于idea中使用lamb表达式报错:ambda expressions are not supported at this language level
			
我使用的是jdk1.8,使用lamb表达式的时候,报错 ambda expressions are not supported at this language level, 后来,设置了 接着重启了 ...
 - vue 生命周期钩子函数
			
实例中的生命周期钩子可以分为以下8种情况: beforeCreate: 实例刚被创建,vue所有属性都还不存在 created: 实例创建完成,但$el还不存在 beforeMount:挂载之前 mo ...
 - android okhttp和webview session共享
			
public static OkHttpClient get(Context context){ OkHttpClient.Builder builder = new OkHttpClient.Bui ...
 - iOS蓝牙架构搭建-2
			
蓝牙架构的搭建 前言:笔者认为,如果只是单纯的传授大家代码怎么敲,那么大家很有可能在实际开发中难以运用.刚好本人曾经参与过多款智能硬件开发的架构搭建,本小节本人就现场带领大家开发出一个通用的蓝牙工具类 ...
 - 502的错误其实不是nginx的问题,要从后端找原因。php-cgi进程数不够用、php执行时间长、或者是php-cgi进程死掉,都会出现502错误。
			
502的错误其实不是nginx的问题,要从后端找原因.php-cgi进程数不够用.php执行时间长.或者是php-cgi进程死掉,都会出现502错误.
 - vue 中的router 配置问题 导致的内存溢出~~~
			
最近的项目用到 vue, 各种踩坑中. 其中一个就是router映射表写的稍有不慎,就会出现内存溢出的问题, 而且也不会具体告诉你哪里出错,所以很是头疼~~~ 出错多了,发现了一些router的一些规 ...
 - git(代码仓库)
			
第1章 git介绍 1.1 参数: 第2章 git管理一个项目 2.1 图示 2.2 cd /项目路径 2.3 git config --globle user.email "邮箱地址&q ...
 - JVM-GC日志分析
			
程序运行时配置如下参数: -Xms20M -Xmx20M -Xmn10M -verbose:gc -XX:+PrintGCDetails -XX:SurvivorRatio= -XX:+PrintGC ...
 - mint 有线网络未管理的解决
			
sudo gedit /etc/NetworkManager/NetworkManager.conf 修改managed=true 参考链接:http://forum.ubuntu.org.cn/vi ...