JavaScript中的模型视图控制器

JavaScript中的模型视图控制器,javascript,model-view-controller,Javascript,Model View Controller,tl;dr:如何以干净的方式在JavaScript中实现MVC? 我正在尝试用JavaScript实现MVC。我用我的代码搜索和重组了无数次,但没有找到合适的解决方案。(代码就是“感觉不对”。) 下面是我现在的打算。它非常复杂,而且很难处理(但仍然比我以前拥有的一堆代码要好)。它有一些丑陋的变通方法,有点违背MVC的目的 如果你真的很勇敢的话,看看这一团糟: // Create a "main model" var main = Model0(); function Model0() {

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
    };
}

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

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

在我看来,我认为JavaScript更多的是一种扩充——因为一个很好的理由,这种吻的心态是存在的。如果您对更好地组织代码感兴趣,那么始终可以选择将相关功能打包到模块(sic)中,并根据需要提取部分。例如,创建一个工厂来进行更复杂的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);

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

至少有两个已建立且可用的MVC框架用于JavaScript和Java。可能还有更多。我已经将JavaScriptMVC用于基于浏览器的应用程序和Air应用程序,并且一直在讨论它——它有它的问题,但我发现它非常有用。
还有其他的解决方案,看看,一个我听说过的好东西。我没用过自己,但打算很快再试一次。我对它的了解不足以恰当地描述它,但对我来说,它似乎是一个在路由、模板系统和ReSTful数据存储上工作的前端控制器。我不确定它是否是MVC,但有相似的成分

我不同意你的看法。在JavaScript中实现MVC可能有点不同,但它的好处对我们来说非常重要。通常与OO语言相关联的设计模式不会因为js不是基于类的而消失

我认为MVC更适合JavaScript应用程序,而不是基于请求(服务器端)的应用程序。这些对象可以在一个单页JavaScript应用程序中停留一段时间——如果不是几个小时的话,也可以是几分钟——并且有一种组织良好的方式来组织它们的交互将使您的代码更加健壮和易于处理

关于您发布的代码,还有其他几点

  • 视图对象负责将事件侦听器应用于DOM元素。这是控制员的工作。视图只是呈现HTML—控制器侦听事件并相应地执行操作
  • 你的模特似乎知道你的观点。模型层应该对视图层了解最少(可能注册为)。保持你的模型干净和切中要害,我指的是业务点-业务逻辑。在js应用程序中,您可能只是代理服务器端模型层,但对于您的理智来说,让您的模型符合业务逻辑而不是其他内容是很重要的。应用程序逻辑是控制器的工作

我完全同意你的观点,但我的应用程序很复杂(它是一个类似Gmail的应用程序——虽然没有那么大,但重点仍然存在)。即使组织方式与您的帖子中的模型相似,代码也是一团糟;我必须找到一些组织模式,这样我才不会发疯。如果MVC很难实现的话,我不需要坚持它,但是在这种情况下,我确实需要一种替代模式。(四年后)使用AngularJS。如果你只是想了解MVC在Javascript中的工作原理,那么询问如何实现它是完全合理的。现在有太多的开发人员使用框架而不真正了解它们是如何工作的。