• 前端 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上。

  • 相关阅读:
    requirejs学习笔记
    Java日期时间处理
    Linux安装ftp服务
    软考真题之设计模式
    《Microsoft Visio 2013 Step by Step.pdf》
    《C++实践之路.pdf》源码
    Python基础与进阶
    微信小程序实战[01]
    常用资源网站
    ECLIPS-S测井系统下的仪器挂接 [CV模块]
  • 原文地址:https://www.cnblogs.com/hellohello/p/7987550.html
Copyright © 2020-2023  润新知