JavaScript中的模型 - 视图 - 控制器

Cas*_*Chu 6 javascript model-view-controller

tl; dr:如何以干净的方式在JavaScript中实现MVC?

我正在尝试用JavaScript实现MVC.我用无数次搜索和重新组织我的代码,但没有找到合适的解决方案.(代码不"感觉正确".)

这就是我现在正在做的事情.它非常复杂并且很难处理(但仍然比我以前的代码堆更好).它有一些丑陋的变通方法,有点破坏了MVC的目的.

不管怎么说,如果你真的很勇敢的话:

// Create a "main model"
var main = Model0();

function Model0() {
    // Create an associated view and store its methods in "view"
    var view = View0();

    // Create a submodel and pass it a function 
    // that will "subviewify" the submodel's view
    var model1 = Model1(function (subview) {
        view.subviewify(subview);
    });

    // Return model methods that can be used by 
    // the controller (the onchange handlers)
    return {
        'updateModel1': function (newValue) {
            model1.update(newValue);
        }
    };
}

function Model1(makeSubView) {
    var info = '';

    // Make an associated view and attach the view 
    // to the parent view using the passed function
    var view = View1();
    makeSubView(view.__view); // Dirty dirty

    // Return model methods that can be used by 
    // the parent model (and so the controller)
    return {
        'update': function (newValue) {
            info = newValue;

            // Notify the view of the new information
            view.events.value(info);
        }
    };
}

function View0() {
    var thing = document.getElementById('theDiv');
    var input = document.getElementById('theInput');

    // This is the "controller", bear with me
    input.onchange = function () {
        // Ugly, uses a global to contact the model
        main.updateModel1(this.value);
    };

    return {
        'events': {},

        // Adds a subview to this view.
        'subviewify': function (subview) {
            thing.appendChild(subview);
        }
    };
}

// This is a subview.
function View1() {

    var element = document.createElement('div');
    return {
        'events': {
            // When the value changes this is 
            // called so the view can be updated
            'value': function (newValue) {
                element.innerHTML = newValue;
            }
        },

        // ..Expose the DOM representation of the subview
        // so it can be attached to a parent view
        '__view': element
    };
}
Run Code Online (Sandbox Code Playgroud)

如何以更清洁的方式在JavaScript中实现MVC?我该如何改进这个系统?或者这是完全错误的方式,我应该遵循另一种模式吗?

meo*_*ouw 6

JavaScript JavaScriptMVCpureMVC至少有几个已建立和可用的MVC框架.可能还有更多.我已经将JavaScriptMVC用于基于浏览器和Air应用并继续回归 - 它有它的问题,但我发现它非常有用.
还有其他解决方案,看看Sammy,这是我听过很多好事的新事物.我没有用过自己,但打算尽快尝试.我不太了解它是否正确描述它,但对我来说,它似乎是一个前端控制器,它适用于路由,模板系统和ReSTful数据存储.我不确定它是否是MVC但具有相似的成分.

我不同意mway的回答.在JavaScript中实现MVC可能有点不同,但它的好处对于组织这个混乱非常重要.通常与OO语言相关的设计模式不会因为js不是基于类的而离开窗口.

我会说MVC比基于请求的(服务器端)应用程序更适合JavaScript应用程序.这些对象可以在一个页面的JavaScript应用程序中闲逛一段时间 - 如果不是几小时,则会有几分钟的时间 - 并且采用组织良好的方式来组织他们的交互将使您的代码更加健壮且易于处理.有关于这个主题的书籍.

关于您发布的代码的其他几点.

  • 视图对象负责将事件侦听器应用于DOM元素.这是控制器的工作.视图只呈现HTML - 控制器侦听事件并相应地执行操作.
  • 您的模型似乎知道您的观点.模型层应该具有对视图层的最小知识(可能被注册为观察者).保持模型清洁,重点,我的意思是业务点 - 业务逻辑.在js应用程序中,您可能只是代理服务器端模型层,但重要的是让您的理智将模型保持在业务逻辑中而不是其他任何内容.应用程序逻辑是控制器的工作


mwa*_*way 0

老实说,MVC 不太适合 Javascript。当然,它可以支持设计的基本原理 - 您可以创建伪类来充当控制器或模型,支持基本继承,并且您可以让它操作或创建任意数量的 DOM 元素,但是您为此付出了代价- 开销、可访问性和可用性。

在我看来,我认为 Javascript 更多的是一种增强——KISS 心态的存在是有充分理由的。如果您对组织代码的更好方法感兴趣,总是可以选择将相关功能打包到模块中(原文如此)并根据需要抽象出部分。例如,创建一个工厂来进行更复杂的 AJAX 请求管理,或者创建一个伪类来处理类似类型的数据。使用控制器的标准基本函数、模型的另一个标准函数等,作为这些对象的新实例的原型可以实现类似的功能……但同样,这有点违背了 Javascript 的本质。

但是,如果您只是为了结构而坚持 MVC 理念,请考虑以下内容:

;(function(window, $) {
    /**
     * Event Object
     * A quick description goes here.
     **/
    var Events = window.Events = {
        'bindTrackables': function() {
            $('a.trackable').live('click', function() {
                if(!_gaq)
                    _gaq = [];
                _gaq.push(['_trackPageview', '/ajax/foobar']);
            });
        },
        'bindSomeEvent': function() {
            // etc
        }
    };

    /**
     * Data Cache
     * I'll need to remember stuff later, so I store it here
     **/
    var Cache = window.Cache = {
        'data': {},
        'store': function(key, value) {
            Cache.data[key] = value;
        },
        'fetch': function(key) {
            return Cache.data[key];
        }
    };

    /**
     * Request Object
     * Stores native AJAX requests for later use
     **/
    var Request = window.Request = {
        'current_requests': [],
        'send': function(url, type, data, callback) {
            Request.current_requests.push($.ajax({
                'url': url,
                'type': type,
                'data': data,
                'callback': callback
            }));
        },
    }

    // add some private logic here
})(window, jQuery);
Run Code Online (Sandbox Code Playgroud)

这是非常基本的,但你明白了。模块化代码是关键……在 JS 中,这比强制应用程序(或语言)适应某种风格更重要。