说明:
作为一个个人项目,我正在尝试为JavaScript创建我自己的轻量级依赖注入版本——有些人可能不同意调用这个DI,因为它没有接口,但我得出的结论是,接口在JS中太夸张了,因为我们可以很容易地进行类型检查。我已经研究过Angular的来源,但我只是觉得我的项目可能过于复杂,无论如何,我都有兴趣尝试自己的学习体验。
问题:
我的问题是,从根本上说,我试图实现的语法是不可能的还是不可能的
我将解释我的语法目标,然后提供错误和代码片段,下面我将发布完整的代码。
语法目标:
我希望组件的创建和依赖项的注入能像这样工作,所有的东西都是组件,任何东西都可以是依赖项。我创建了一个具有字符串路径的作用域,使用"/scopeName/subScopeName:componentName"
来选择一个作用域,这样代码用户就可以在定义组件的同时选择该作用域,并使用":"
从作用域中选择一个组件。
var JHTML = new Viziion('JHTML');
JHTML.addScope('/generate');
/* ...snip - see full code for the process component - snip ... */
JHTML.addComponent('/generate:init', function (jsonInput, process) {
var html = process(jsonInput);
return html;
}).inject([null, '/generate:process']);
inject
函数只是按照组件参数的预期顺序获取一组组件路径。null
可以用于跳过,允许直接输入参数,如上所示。
我还有一个我称之为钩子的东西,它是存储在某个地方的组件,然后有一个函数returnUserHandle
,它将返回一个仅由钩子组成的对象,所以所有的函数都隐藏在闭包中,你可以向代码用户提供可用的方法,干净而简单,并且可以在没有布线的情况下将最终产品作为库生成,不需要将我的DI框架作为依赖项。希望这是有道理的。
错误:
现在,运行代码(这是一个通过解析JSON结构生成HTML的非常简单的库)时,我在var html = process(jsonInput);
行中得到了process
未定义的错误。我很难理解这是一个基本的设计问题,还是一个bug。也许这种语法是不可能的,我希望你能告诉我
代码:
这是代码和JS Bin的链接。
/* Dependency Injection Framework - viziion.js */
function Viziion(appName) {
if (typeof appName == 'string') {
var that = this;
this.name = appName;
this.focus = null;
this.scope = {
'/': {
'subScopes': {},
'components': {}
}
};
this.hooks = {};
this.addScope = function(scopeName) {
if (typeof scopeName == 'string') {
var scopeArray = scopeName.split('/');
var scope = that.scope['/'];
for (var i = 0; i < scopeArray.length; i++) {
if (scopeArray[i] !== "") {
if (scope.subScopes[scopeArray[i]]) {
scope = scope.subScopes[scopeArray[i]];
} else {
scope.subScopes[scopeArray[i]] = {
'subScopes': {},
'components': {}
};
}
}
}
} else {
throw 'Scope path must be a string.';
}
return that;
};
this.addComponent = function(componentName, func) {
if (typeof componentName == 'string') {
var scopeArray = componentName.split(':');
if (scopeArray.length == 2) {
var scope = that.scope['/'];
var scopeName = scopeArray[1];
scopeArray = scopeArray[0].split('/');
for (var i = 0; i < scopeArray.length; i++) {
if (scopeArray[i] !== "") {
if ((i + 1) === scopeArray.length) {
scope.components[scopeName] = func;
that.focus = scope.components[scopeName];
} else if (scope.subScopes[scopeArray[i]]) {
scope = scope.subScopes[scopeArray[i]];
} else {
throw 'Scope path is invalid.';
}
}
}
} else {
throw 'Path does not include a component.';
}
} else {
throw 'Component path must be a string1.';
}
return that;
};
this.returnComponent = function(componentName, callback) {
if (typeof componentName == 'string') {
var scopeArray = componentName.split(':');
if (scopeArray.length == 2) {
var scope = that.scope['/'];
var scopeName = scopeArray[1];
scopeArray = scopeArray[0].split('/');
for (var i = 0; i < scopeArray.length; i++) {
if (scopeArray[i] !== "") {
if ((i + 1) === scopeArray.length) {
//console.log('yep1');
//console.log(scope.components[scopeName]);
callback(scope.components[scopeName]);
} else if (scope.subScopes[scopeArray[i]]) {
scope = scope.subScopes[scopeArray[i]];
} else {
throw 'Scope path is invalid.';
}
}
}
} else {
throw 'Path does not include a component.';
}
} else {
throw 'Component path must be a string2.';
}
};
this.addHook = function(hookName, func) {
if (typeof hookName == 'string') {
that.hooks[hookName] = func;
that.focus = that.hooks[hookName];
} else {
throw 'Hook name must be a string.';
}
return that;
};
this.inject = function(dependencyArray) {
if (dependencyArray) {
var args = [];
for (var i = 0; i < dependencyArray.length; i++) {
if (dependencyArray[i] !== null) {
that.returnComponent(dependencyArray[i], function(dependency) {
args.push(dependency);
});
}
}
console.log(that.focus);
that.focus.apply(null, args);
return that;
}
};
this.returnUserHandle = function() {
return that.hooks;
};
} else {
throw 'Viziion name must be a string.';
}
}
/* JSON HTML Generator - A Simple Library Using Viziion */
var JHTML = new Viziion('JHTML');
JHTML.addScope('/generate');
JHTML.addComponent('/generate:process', function(children) {
var html = [];
var loop = function() {
for (var i = 0; i < children.length; i++) {
if (children[i].tag) {
html.push('<' + tag + '>');
if (children[i].children) {
loop();
}
html.push('</' + tag + '>');
return html;
} else {
throw '[JHTML] Bad syntax: Tag type is not defined on node.';
}
}
};
}).inject();
JHTML.addComponent('/generate:init', function(jsonInput, process) {
console.log(process);
var html = process(jsonInput);
return html;
}).inject([null, '/generate:process']);
JHTML.addHook('generate', function(jsonInput, init) {
var html = init(jsonInput);
return html;
}).inject([null, '/generate:init']);
handle = JHTML.returnUserHandle();
/* HTML Generator Syntax - Client */
var htmlChunk = [{
tag: '!DOCTYPEHTML'
}, {
tag: 'html',
children: [{
tag: 'head',
children: []
}, {
tag: 'body',
children: []
}]
}];
console.log(handle.generate(htmlChunk));
我试图实现的语法是不可能的还是不可能的?
这是绝对可能的,我相信只要稍微修正一下错误,它就会很好。
您所描述的基本上与异步模块定义(AMD)相同,后者广泛用于处理代码依赖关系。
与其继续追求你自己版本的相同概念,我建议你尝试一下requirejs,并在你的项目中遵循现有的标准。