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

发布于 2024-09-05 04:02:40 字数 2385 浏览 4 评论 0原文

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?我该如何改进这个系统?或者这是完全错误的方法,我应该遵循另一种模式吗?

tl;dr: How does one implement MVC in JavaScript in a clean way?

I'm trying to implement MVC in JavaScript. I have googled and reorganized with my code countless times but have not found a suitable solution. (The code just doesn't "feel right".)

Here's how I'm going about it right now. It's incredibly complicated and is a pain to work with (but still better than the pile of code I had before). It has ugly workarounds that sort of defeat the purpose of MVC.

And behold, the mess, if you're really brave:

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

How does one implement MVC in JavaScript in a cleaner way? How can I improve this system? Or is this the completely wrong way to go, should I follow another pattern?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

放赐 2024-09-12 04:02:40

至少有几个已建立且可用的 JavaScript MVC 框架 JavaScriptMVCpureMVC。可能还有更多。我已经将 JavaScriptMVC 用于基于浏览器的应用程序和 Air 应用程序,并且不断回来使用它 - 它有其问题,但我发现它非常有用。
还有其他解决方案,看看 Sammy,我的一个新东西听说过好话。我自己还没用过,但打算尽快尝试。我对它了解不够,无法正确描述它,但对我来说,它似乎是一个在路由、模板系统和 ReSTful 数据存储上工作的前端控制器。我不确定它是否是 MVC 但有类似的成分。

我不同意mway的回答。 MVC 在 JavaScript 中实现可能有点不同,但它的好处对于组织非常重要这团乱麻。通常与 OO 语言相关的设计模式不会仅仅因为 js 不是基于类的而被抛弃。

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

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

  • 视图对象负责将事件侦听器应用于 DOM 元素。这是控制器的工作。视图仅呈现 HTML - 控制器侦听事件并采取相应的操作。
  • 你的模特似乎知道你的观点。模型层应该对视图层有最少的了解(可能注册为观察者)。保持你的模型简洁明了,我的意思是业务点——业务逻辑。在 js 应用程序中,您可能只是代理服务器端模型层,但保持模型符合业务逻辑对您的理智非常重要。应用程序逻辑是控制器的工作

There are at least a couple of established and usable MVC frameworks for JavaScript JavaScriptMVC and pureMVC. There are probably more. I've used JavaScriptMVC for browser based and Air apps and keep coming back to it - it has its problems but I've found it to be quite useful.
There are other solutions too, have a look at Sammy, a new thing I've heard good things about. I haven't used myself but intend to try soon. I don't know enough about it to describe it properly, but to me it seems like a front controller which works on routes, a templating system and ReSTful data stores. I'm not sure if it is MVC but has similar ingredients.

I have to disagree with mway's answer. MVC may be a bit diferent to implement in JavaScript but its benefits are very important to organising this mess. The design patterns usually associated with OO languages don't go out the window just because js isn't class based.

I would say that MVC is more suitable for JavaScript apps than for request based (server side) applications. Those objects can hang around for a while in a one page JavaScript app - minutes if not hours - and having a well organised way of organising their interaction will make your code much more robust and easy to deal with. There are books on the subject.

A couple of other points regarding the code you posted.

  • The view objects have responsibility for applying event listeners to DOM elements. This is the controller's job. The view just renders the HTML - the controller listens for the events and acts accordingly.
  • Your models seem to know your views. The model layer should have minimal knowledge of the view layer (perhaps being registered as observers). Keep your model clean and to the point, I mean the business point - business logic. In js apps you may just be proxying for a sever side model layer but it is important for your sanity to keep your model to the business logic and nothing else. Application logic is the controllers job
活泼老夫 2024-09-12 04:02:40

老实说,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);

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

To be honest, MVC isn't well-suited for Javascript. It can support the basic fundamentals of the design, sure - you can create pseudoclasses to act as controllers or models, support basic inheritance, and you can have it manipulate or create any number of DOM elements, but there's a price that you pay for that - in overhead, accessibility, and usability.

In my opinion, I consider Javascript more of an augmentation - the KISS mentality exists for a good reason. If you're interested in better ways to organize your code, there's always the option of packaging related functionality into modules (sic) and abstracting out portions as appropriate. For example, creating a factory to do more complex AJAX request management, or a pseudoclass to handle processing of similar types of data. Using a standard base function for controllers, another for models, etc, as prototypes for new instances of those objects can accomplish similar functionality... but again, it's sort of going against the grain of Javascript.

However, if you're stuck on the MVC idea just for the sake of structure, consider something like the following:

;(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);

It's extremely basic, but you get the idea. Modular code is key... in JS, this is more important than forcing your application (or the language) to fit a certain style.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文