JavaScript中的模型 - 视图 - 控制器
tl; dr:如何在JavaScript中以干净的方式实现MVC?JavaScript中的模型 - 视图 - 控制器
我想在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更多的是一种增强 - 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中,这比强制应用程序(或语言)适合某种风格更重要。
我完全同意你的观点,但我的应用程序很复杂(这是一个Gmail应用程序 - 几乎没有那么大,但关键还是在于)。即使组织与你的文章中的模型类似,代码也是一团糟。我必须找到一些组织模式,所以我没有发疯。如果实施(好)很麻烦,我不需要坚持MVC,但是在那种情况下,我确实需要替代模式。 – 2010-06-14 19:23:04
对于JavaScript JavaScriptMVC和pureMVC,至少有一些已建立和可用的MVC框架。可能还有更多。我已经使用基于浏览器和Air应用程序的JavaScriptMVC并继续回到它 - 它有它的问题,但我发现它非常有用。
还有其他的解决方案,看看Sammy,这是我听到的好消息。我没有用过自己,但打算尽快尝试。我对它的描述不够充分,但对我来说,它似乎是一个在路线上工作的前端控制器,一个模板系统和ReSTful数据存储。我不确定它是否是MVC,但具有相似的成分。我不得不不同意mway's answer。 MVC在JavaScript中可能有点不同,但其好处对于organising this mess非常重要。通常与面向对象语言相关的设计模式不会因为js不是基于类而离开窗口。
我会说MVC比基于请求的(服务器端)应用程序更适合JavaScript应用程序。这些对象可以在一页JavaScript应用程序中停留一段时间 - 分钟(如果不是几个小时) - 并且组织良好的组织交互的方式将使您的代码更加健壮并易于处理。 There are books on the subject.
关于您发布的代码的其他几点。
- 视图对象负责将事件侦听器应用于DOM元素。这是控制员的工作。该视图只呈现HTML - 控制器监听事件并相应地执行操作。
- 您的模型似乎知道您的意见。模型层应该对视图层有最少的知识(可能注册为observers)。保持你的模型干净,关键点,我的意思是业务点 - 业务逻辑。在js应用程序中,您可能只是代理服务器端的模型层,但重要的是让您的模型保持业务逻辑,而不是其他任何东西。应用程序逻辑是控制器作业
(四年后)使用AngularJS。 – 2014-04-21 09:45:42
如果您只是想了解MVC如何在Javascript中工作,那么询问如何实现它是非常合理的。太多的开发者现在都在使用框架,而没有真正理解他们的工作方式。 – NobodyReally 2014-08-07 15:38:42