Модель-Вид-Контроллер в JavaScript - PullRequest
6 голосов
/ 14 июня 2010

tl; dr: Как правильно реализовать MVC в JavaScript?

Я пытаюсь реализовать MVC в JavaScript. Я гуглил и реорганизовывал свой код бесчисленное количество раз, но не нашел подходящего решения. (Код просто «не чувствуется правильным».)

Вот как я сейчас это сделаю. Это невероятно сложно и с ней трудно работать (но все же лучше, чем куча кода, которую я имел раньше). У него ужасные обходные пути, которые побеждают цель 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
    };
}

Как лучше реализовать MVC в JavaScript? Как я могу улучшить эту систему? Или это совершенно неправильный путь, я должен следовать другому шаблону?

Ответы [ 2 ]

6 голосов
/ 15 июня 2010

Существует как минимум пара установленных и используемых сред MVC для JavaScript JavaScriptMVC и pureMVC . Есть, вероятно, больше. Я использовал JavaScriptMVC для браузерных приложений и приложений Air и продолжаю возвращаться к нему - у него есть свои проблемы, но я нашел его весьма полезным.
Есть и другие решения, взгляните на Сэмми , новость, о которой я слышал хорошие вещи. Я не использовал себя, но собираюсь попробовать в ближайшее время. Я не знаю достаточно об этом, чтобы описать это должным образом, но мне кажется, что это фронт-контроллер, работающий на маршрутах, система шаблонов и хранилища данных ReSTful. Я не уверен, что это MVC, но имеет похожие ингредиенты.

Я должен не согласиться с ответом mway . MVC может немного отличаться от реализации в JavaScript, но его преимущества очень важны для организации этого беспорядка . Шаблоны проектирования, обычно связанные с языками OO, не выходят за рамки только потому, что js не основан на классах.

Я бы сказал, что MVC больше подходит для приложений JavaScript, чем для приложений на основе запросов (на стороне сервера). Эти объекты могут ненадолго задерживаться в одностраничном приложении JavaScript - минуты, если не часы - и хорошо организованный способ организации их взаимодействия сделает ваш код гораздо более надежным и простым в обращении. Есть книги на эту тему.

Несколько других замечаний относительно кода, который вы разместили.

  • Объекты представления отвечают за применение слушателей событий к элементам DOM. Это работа контроллера. Представление просто отображает HTML - контроллер прослушивает события и действует соответственно.
  • Кажется, ваши модели знают ваши взгляды. Слой модели должен иметь минимальные знания о слое представления (возможно, он зарегистрирован как наблюдатели ). Держите вашу модель в чистоте, и я имею в виду бизнес-логику. В приложениях js вы, возможно, просто используете прокси для уровня модели стороны, но для вашего здравого смысла важно сохранить вашу модель в соответствии с бизнес-логикой и ничем иным. Логика приложения - это работа контроллеров
0 голосов
/ 14 июня 2010

Если честно, MVC не очень подходит для Javascript.Конечно, он может поддерживать базовые принципы проектирования - вы можете создавать псевдоклассы, выступающие в качестве контроллеров или моделей, поддерживать базовое наследование, и вы можете управлять им или создавать любое количество элементов DOM, но за это вы платите цену- в накладных расходах, доступности и удобстве использования.

По моему мнению, я считаю Javascript скорее дополнением - менталитет KISS существует по уважительной причине.Если вы заинтересованы в более эффективных способах организации своего кода, всегда есть возможность упаковать связанные функциональные возможности в модули (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 это важнее, чем принуждать ваше приложение (или язык) к определенному стилю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...