首先咱们用大白话来理解一次,依赖注入就是我有一个东西,我平时不用,我把这个东西放在你那里,在我用的时候你拿给我。数组
这个时候咱们已经初步有了概念,咱们在用代码来消化这个概念bash
首先咱们来先建立一个inject的对象,对象下有个三个属性分别为app
const inject = {
dependencies: {},
register: function(key, value) {
this.dependencies[key] = value;
},
resolve: function(deps, func, scope){
let arr = [];
for (let i = 0 ; i < deps.length ; i++) {
if (this.dependencies.hasOwnProperty(deps[i])) {
arr.push(this.dependencies[deps[i]])
}
}
return function(){
func.apply(scope||{},arr);
}
},
}复制代码
嗯, 大概就是这个,即然已经把初步的想法实现,咱们如今就来试试到底可不能够注入首先实现我有一个东西,而且把这个东西存在你那,那么咱们用register方法来注册两个函数
inject.register('$http', {
'get': function() {
return '我是依赖注入的$http下的一个函数';
}
});
inject.register('$scope', {
'test': ''
});复制代码
这个时候我须要用到我前面存放在你那里东西,你得拿给我ui
let MyController = function($scope,$http){
console.log(`MyController-result:${$http.get()}`)
}
MyController = inject.resolve(['$scope','$http'],MyController)
MyController(); // MyController-result:我是依赖注入的$http下的一个函数复制代码
嗯,完美,这样就简单的实现咱们的注入,但咱们仔细一下,若是这个时候咱们把这个依赖注入的顺序变换一下是报错的,由于他们是一一对应的,因此咱们还得来改造一下resolve这个方法,this
resolve: function(func, scope){
let arr = [];
// 这些正则是在angular的源码里找来的
// 首先把这个函数toString,而后FN_ARGS匹配出来函数的参数,这个参数就是咱们依赖的表
// 那么这个时候咱们已经拿到依赖的表了,咱们按照这个表里取出相对应的函数体给他就完了
let FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
let STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
let fnText = func.toString().replace(STRIP_COMMENTS, '');
let argDecl = fnText.match(FN_ARGS);
let deps = argDecl[1].split(',');
for (let i = 0 ; i < deps.length ; i++) {
if (this.dependencies.hasOwnProperty(deps[i])) {
arr.push(this.dependencies[deps[i]])
}
}
return function(){
func.apply(scope||{},arr);
}
}复制代码
固然使用的时候也得改一下spa
let MyController = function($scope,$http){
console.log(`MyController-result:${$http.get()}`)
}
MyController = inject.resolve(MyController)
MyController(); // MyController-result:我是依赖注入的$http下的一个函数复制代码
看上去有点像模样了,这时候我以为应该有人会提出问题,嗯,对,就是还有问题,咱们知道上线前咱们通常会把项目静态资源打包,function($scope,$http)会打成相似于function(a,b)这种,那么这个时候还怎么去打到对应的函数体呢 ? 咱们再来改写一下resolve方法code
resolve: function(func, scope) {
let deps;
// 若是传入的函数是一个数组,大概长这样[a,b,function(a,b){}],那么咱们删掉function(){}这部分,只留下咱们的依赖部分,这样就解决了打包压缩时的问题
if (isArray(func)) {
let last = func.length - 1;
deps = func.slice(0, last);
func = func[last]
} else {
let FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
let STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
let fnText = func.toString().replace(STRIP_COMMENTS, '');
let argDecl = fnText.match(FN_ARGS);
deps = argDecl[1].split(',');
}
let arr = [];
for (let i = 0; i < deps.length; i++) {
if (this.dependencies.hasOwnProperty(deps[i])) {
arr.push(this.dependencies[deps[i]])
}
}
return function() {
func.apply(scope || {}, arr);
}
}复制代码
固然使用的时候仍是得改改对象
let MyController = ['$scope', '$http', function($scope, $http) {
console.log(`MyController-result:${$http.get()}`)
}];
MyController = inject.resolve(MyController)
MyController(); // MyController-result:我是依赖注入的$http下的一个函数复制代码
这样咱们一个简易的dependencies inject就完成了,angular的实现思路也是如此ci