[英]What is the right way to wire together 2 javascript objects?
I'm currently facing a conundrum: What is the right way to wire together 2 javascript objects? 我目前面临一个难题:将两个javascript对象连接在一起的正确方法是什么?
Imagine an application like a text editor with several different files. 想象一下像文本编辑器这样的应用程序,它有几个不同的文件。 I have some HTML page that represents the view for the notebook.
我有一些HTML页面代表笔记本的视图。 I have a file notebook.js that contains class definitions for NotebookController and Notebook View.
我有一个文件notebook.js,其中包含NotebookController和Notebook View的类定义。
NotebookControler object responsible for performing business logic on the Notebook like "Save Notebook," "Load Notebook," "New Notebook." NotebookControler对象负责在笔记本上执行业务逻辑,如“保存笔记本”,“加载笔记本”,“新笔记本”。 NotebookView is responsible for managing the HTML that is used for presentation.
NotebookView负责管理用于演示的HTML。 It does low level stuff like "get/set notebook body" "get/set notebook name."
它做低级别的东西,如“获取/设置笔记本电脑主体”“获取/设置笔记本名称”。 It also listens for DOM events (onClick) and fires business events (saveNotebook).
它还侦听DOM事件(onClick)并触发业务事件(saveNotebook)。 This is my attempt at the Passive View pattern.
这是我对被动视图模式的尝试。
I want my javascript client-side code to be object-oriented, separated concerns, and unit-testable. 我希望我的javascript客户端代码是面向对象的,分离的关注点和单元可测试的。 I want to test NotebookController with a mock NotebookView and vice versa.
我想用模拟NotebookView测试NotebookController,反之亦然。 This means that I can't just instantiate a NotebookView inside the NotebookController.
这意味着我不能只在NotebookController中实例化NotebookView。 So do I
我也是
In Java, the choice is a natural one: use Spring. 在Java中,选择是自然的:使用Spring。 But that doesn't seem very JavaScript-y.
但这似乎不是JavaScript-y。 What's the right thing to do?
什么是正确的做法?
Dependency injection is probably your best bet. 依赖注入可能是你最好的选择。 Compared to Java, some aspects of this are easier to do in JS code, since you can pass an object full of callbacks into your NotebookController.
与Java相比,JS代码中的某些方面更容易实现,因为您可以将一个充满回调的对象传递到NotebookController中。 Other aspects are harder, because you don't have the static code analysis to formalize the interface between them.
其他方面更难,因为您没有静态代码分析来形式化它们之间的接口。
Thanks for the insight. 感谢您的见解。 I ended up writing a simple JavaScript dependency injection utility.
我最终编写了一个简单的JavaScript依赖注入实用程序。 After debating for a while and your comments, it occured to me that DI was really the right answer because:
经过一段时间的辩论和你的评论之后,我发现DI确实是正确答案,因为:
So here's the DI utility: 所以这是DI工具:
var Dependency = function(_name, _instance, _dependencyMap) {
this.name = _name;
this.instance = _instance;
this.dependencyMap = _dependencyMap;
}
Dependency.prototype.toString = function() {
return this.name;
}
CONCORD.dependencyinjection = {};
CONCORD.dependencyinjection.Context = function() {
this.registry = {};
}
CONCORD.dependencyinjection.Context.prototype = {
register : function(name, instance, dependencyMap) {
this.registry[name] = new Dependency(name, instance, dependencyMap);
},
get : function(name) {
var dependency = this.registry[name];
return dependency != null ? dependency.instance : null;
},
init : function() {
YAHOO.log("Initializing Dependency Injection","info","CONCORD.dependencyinjection.Context");
var registryKey;
var dependencyKey;
var dependency;
var afterDependenciesSet = [];
for (registryKey in this.registry) {
dependency = this.registry[registryKey];
YAHOO.log("Initializing " + dependency.name,"debug","CONCORD.dependencyinjection.Context");
for(dependencyKey in dependency.dependencyMap) {
var name = dependency.dependencyMap[dependencyKey];
var instance = this.get(name);
if(instance == null) {
throw "Unsatisfied Dependency: "+dependency+"."+dependencyKey+" could not find instance for "+name;
}
dependency.instance[dependencyKey] = instance;
}
if(typeof dependency.instance['afterDependenciesSet'] != 'undefined') {
afterDependenciesSet.push(dependency);
}
}
var i;
for(i = 0; i < afterDependenciesSet.length; i++) {
afterDependenciesSet[i].instance.afterDependenciesSet();
}
}
}
I would say, just wire them together: 我会说,只需将它们连接在一起:
function wireTogether() {
var v = new View();
var c = new Controller();
c.setView(v);
}
But then of course another question raises - how do you test the wireTogether() function? 但当然另一个问题提出了 - 你如何测试wireTogether()函数?
Luckily, JavaScript is a really dynamic language, so you can just assign new values to View and Controller: 幸运的是,JavaScript是一种非常动态的语言,因此您只需为View和Controller分配新值:
var ok = false;
View.prototype.isOurMock = true;
Controller.prototype.setView = function(v) {
ok = v.isOurMock;
}
wireTogether();
alert( ok ? "Test passed" : "Test failed" );
I have a inversion of control library for javascript, I'm pretty happy with it. 我有一个javascript控件库的反转,我很高兴。 https://github.com/fschwiet/jsfioc .
https://github.com/fschwiet/jsfioc 。 It also supports events, so if you want to have a startup event thats fine.
它还支持事件,所以如果你想要一个很好的启动事件。 It could use more documentation...
它可以使用更多文档......
http://github.com/fschwiet/jsfioc http://github.com/fschwiet/jsfioc
Another (newer?) option, which has better documentation and support, is requireJS (http://requirejs.org/). 另一个(较新的?)选项,具有更好的文档和支持,是requireJS(http://requirejs.org/)。
还有一个用于JavaScript依赖注入的框架: https : //github.com/briancavalier/wire
I'll try to take a stab at this, but it will be a little difficult without seeing any actual code. 我会尝试对此进行尝试,但如果没有看到任何实际代码,那将会有点困难。 Personally, I've never seen anybody do such a specific attempt at (M)VC with JavaScript or IoC for that matter.
就个人而言,我从未见过有人在(M)VC上使用JavaScript或IoC进行过这样的特定尝试。
First of all, what are you going to test with? 首先,你要测试什么? If you haven't already, check out the YUI Test video which has some good info on unit testing with javascript.
如果您还没有,请查看YUI测试视频 ,其中包含有关使用javascript进行单元测试的一些好信息。
Secondly, when you say "the best way to wire up that aggregation" I would probably just do it as a setter w/the controller 其次,当你说“连接聚合的最佳方式”时,我可能会把它当作一个带控制器的setter
// Production
var cont = new NotebookController();
cont.setView( new NotebookView() );
// Testing the View
var cont = new NotebookController();
cont.setView( new MockNotebookView() );
// Testing the Controller
var cont = new MockNotebookController();
cont.setView( new NotebookView() );
// Testing both
var cont = new MockNotebookController();
cont.setView( new MockNotebookView() );
But this makes some big assumption on how you've designed your controller and view objects already. 但是这对你如何设计控制器和查看对象做了一些很大的假设。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.