当前位置: 移动技术网 > IT编程>脚本编程>AngularJs > 自学实现angularjs依赖注入

自学实现angularjs依赖注入

2018年05月03日  | 移动技术网IT编程  | 我要评论
    在用angular依赖注入时,感觉很好用,他的出现是 为了“削减计算机程序的耦合问题” ,我怀着敬畏与好奇的心情,轻轻的走进了angu

    在用angular依赖注入时,感觉很好用,他的出现是 为了“削减计算机程序的耦合问题” ,我怀着敬畏与好奇的心情,轻轻的走进了angular源码,看看他到底是怎么实现的,我也想写个这么牛逼的功能。于是就模仿着写了一个,如果有什么不对,请大家批评指正。

     其实刚开始的时候我也不知道怎么下手,源码中有些确实晦涩难懂,到现在我也没有看明白,于是我就静下心想一想,他是怎么用的,如下所示:

angular.module(/*省略*/)
 .factory("xxxservice", ['xx',function (xx) {
  return {
    //省略
  }
 }])
 .controller('iicontroller',['xxxservice',function(xxxservice){
  //省略
 }]);
/*...方法省略..*/

    看看上面严格模式下的使用方式,先不去看源码,如何实现service重用,controller不重用呢? 我就按照自己的想法创建一个cache用于保存service,controller 只运行一次,不保存到cache中。

有了点思路,就把该有的东西先写了,

(function (global) {
 function createinjector(cache){
  this.cache=cache;//用于保存service的cache
 }
 function angular(){}
 angular.module=function(){
  var moduleobj={};
  return {
   injector:new createinjector(moduleobj),
   factory:function(name,fn){
   },
   controller:function(name,fn){
   }
  }
 };
 global.angular = angular;
})(window);

    上面两个构造函数,一个是创建构造器,一个是angular 的静态module(不用创建直接用 "构造函数名.方法名",这里就是想模仿angular.module())方法,这里angular module 的方法我简写了,他也有依赖注入,但是我能力有限,先研究了controller和service的注入。上面的方法名字都是我copy于源码中的,这里我就不解释他们的具体意义了。

由于我们研究的是依赖注入,真正的核心代码如下:

var arrow_arg = /^([^\(]+?)=>/;
var fn_args = /^[^\(]*\(\s*([^\)]*)\)/m;
var strip_comments = /((\/\/.*$)|(\/\*[\s\s]*?\*\/))/mg;
function isarray(obj){
 return object.prototype.tostring.call(obj) === '[object array]';
}
function stringifyfn(fn) {
 return fn.tostring();
}

function extractargs(fn) {
 var fntext = stringifyfn(fn).replace(strip_comments, ''),
 args= fntext.match(arrow_arg) || fntext.match(fn_args);
 return args[1].split(',');
}
function createinjector(cache){
 this.cache=cache;
}
createinjector.prototype={
 constructor:createinjector,
 invoke:function(fn,self){
  var argsname= extractargs(fn),argsfn=[];
  argsname.foreach(function(arg){
   argsfn.push(this.cache[arg]);
  },this);
  if(isarray(fn)){
   return fn[fn.length-1].apply(self,argsfn);
  }else{
   return fn.apply(self,argsfn);
  }
 }
};

其中上面的正则表达式是复制于源码中的,代码原理是:

   (1)把传来的function tostring(),然后用正则match出所传参数名,用split把参数分割成参数数组;

   (2)循环参数数组,在cache中找到此参数名下的函数,push到一个函数数组中;

   (3)利用apply,把函数数组当成参数,去执行函数;

对于所传的fn, 判断是数组格式,还是普通的,如果是数组就apply最后的一个值,也就是函数,否则就是fn自己。

   上面的我没有做错误处理,比如注入的找不到等等一些问题,有兴趣自己加上吧。

最后所有代码如下,大家可以复制运行:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>angular injector demo</title>
</head>
<body>
<script>
(function (global) {
  var arrow_arg = /^([^\(]+?)=>/;
  var fn_args = /^[^\(]*\(\s*([^\)]*)\)/m;
  var strip_comments = /((\/\/.*$)|(\/\*[\s\s]*?\*\/))/mg;
  function isarray(obj){
    return object.prototype.tostring.call(obj) === '[object array]';
  }
  function stringifyfn(fn) {
    return fn.tostring();
  }

  function extractargs(fn) {
    var fntext = stringifyfn(fn).replace(strip_comments, ''),
    args= fntext.match(arrow_arg) || fntext.match(fn_args);
    return args[1].split(',');
  }
  function createinjector(cache){
    this.cache=cache;
  }
  createinjector.prototype={
    constructor:createinjector,
    invoke:function(fn,self){
      var argsname= extractargs(fn),argsfn=[];
      argsname.foreach(function(arg){
        argsfn.push(this.cache[arg]);
      },this);
      if(isarray(fn)){
        return fn[fn.length-1].apply(self,argsfn);
      }else{
        return fn.apply(self,argsfn);
      }
    }
  };
  function angular(){}
  angular.module=function(){
    var moduleobj={};
     return {
       injector:new createinjector(moduleobj),
       factory:function(name,fn){
         moduleobj[name]=this.injector.invoke(fn);
         return this;
       },
       controller:function(name,fn){
         this.injector.invoke(fn);
         return this;
       }
     }
  };
  global.angular = angular;
})(window);


angular.module()
  .factory('cacheservice',[function(){
    return {};
  }])
  .factory("userinfoservice", ['cacheservice',function (cacheservice) {
    return {
      getuserinfo:function(){
        return cacheservice.userinfo;
      },
      setuserinfo:function(value){
        cacheservice.userinfo=value;
      }
    }
  }])
  .controller('usercontroller',['userinfoservice',function(userinfoservice){
    userinfoservice.setuserinfo({id:'qqqq11234',name:'zhanglearing'});
    console.log(userinfoservice.getuserinfo());
  }]);
</script>
</body>
</html>

谢谢大家!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网