这种"DI"结构是不可能的,还是我应该寻找错误?



说明:

作为一个个人项目,我正在尝试为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,并在你的项目中遵循现有的标准。

相关内容

最新更新