AngularJS - 依赖注入:初学者指南
你好,有抱负的程序员们!今天,我们将开始一段激动人心的旅程,进入AngularJS的世界,以及它最强大的特性之一:依赖注入(DI)。如果这些术语现在听起来像是一堆胡言乱语,别担心 - 到了这个教程的结尾,你会像专业人士一样熟练地使用它们!
什么是依赖注入?
在我们深入细节之前,让我们先了解一下依赖注入是什么。想象你正在烤蛋糕。如果你不需要自己收集所有材料,而是在你需要的时候,有人递给你确切所需的东西,那不是很好吗?这正是依赖注入在编程中做的事情 - 它为你提供代码(蛋糕)正常运行所需的组件(材料)。
现在,让我们探索AngularJS实现依赖注入的不同方式。
值(Value)
值是依赖注入最简单的形式。它就像给你的蛋糕制作函数传递一个单独的材料。
var app = angular.module('myApp', []);
app.value('playerName', 'LeBron James');
app.controller('PlayerCtrl', function($scope, playerName) {
$scope.name = playerName;
});
在这个例子中,我们创建了一个名为 'playerName' 的值,并将其注入到我们的控制器中。控制器现在可以使用这个值,就像它是本地变量一样。
工厂(Factory)
工厂就像蛋糕预混粉 - 它是一个创建并返回对象的函数。它比值更复杂,但给你提供了更多的灵活性。
app.factory('playerFactory', function() {
return {
name: 'Stephen Curry',
team: 'Golden State Warriors',
getInfo: function() {
return this.name + ' plays for ' + this.team;
}
};
});
app.controller('PlayerCtrl', function($scope, playerFactory) {
$scope.playerInfo = playerFactory.getInfo();
});
在这里,我们创建了一个返回带有属性和方法的对象的工厂。控制器现在可以使用这个工厂来访问球员的信息。
服务(Service)
服务与工厂类似,但它返回的是一个函数的实例,而不是一个对象。可以把它想象成只制作一种蛋糕的专用面包店。
app.service('PlayerService', function() {
this.name = 'Kevin Durant';
this.team = 'Phoenix Suns';
this.getInfo = function() {
return this.name + ' plays for ' + this.team;
};
});
app.controller('PlayerCtrl', function($scope, PlayerService) {
$scope.playerInfo = PlayerService.getInfo();
});
工厂与服务之间的主要区别在于它们的实例化方式。服务始终是单例的 - 在你的整个应用程序中只有一个实例。
提供者(Provider)
提供者是AngularJS中依赖注入最复杂的形式。它就像一个设备齐全的面包店,可以制作任何类型的蛋糕,使用任何材料,以任何你想要的方式。
app.provider('playerProvider', function() {
var defaultName = 'Giannis Antetokounmpo';
return {
setName: function(name) {
defaultName = name;
},
$get: function() {
return {
getName: function() {
return defaultName;
}
};
}
};
});
app.config(function(playerProviderProvider) {
playerProviderProvider.setName('Luka Doncic');
});
app.controller('PlayerCtrl', function($scope, playerProvider) {
$scope.playerName = playerProvider.getName();
});
提供者允许你在应用程序运行之前配置服务。在这个例子中,我们正在配置阶段的玩家名称,这个阶段在主应用程序之前运行。
常量(Constant)
常量类似于值,但它可以在应用程序的配置阶段注入。就像你无论制作哪种蛋糕都始终遵循的食谱。
app.constant('GAME_DURATION', 48);
app.config(function(GAME_DURATION) {
console.log('A basketball game lasts ' + GAME_DURATION + ' minutes');
});
app.controller('GameCtrl', function($scope, GAME_DURATION) {
$scope.duration = GAME_DURATION;
});
常量对于在应用程序中始终不变的价值非常有用。
示例:构建一个篮球队伍管理器
现在我们已经涵盖了所有类型的依赖注入,让我们在更复杂的示例中将它们全部放在一起。
var app = angular.module('basketballApp', []);
// 常量
app.constant('MAX_PLAYERS', 15);
// 值
app.value('teamName', 'Angular All-Stars');
// 工厂
app.factory('PlayerFactory', function() {
var players = [];
return {
addPlayer: function(name) {
players.push(name);
},
getPlayers: function() {
return players;
}
};
});
// 服务
app.service('CoachService', function() {
this.name = 'Coach Angular';
this.motivate = function() {
return this.name + ' says: Let\'s win this game!';
};
});
// 提供者
app.provider('gameProvider', function() {
var venue = 'Home Court';
return {
setVenue: function(v) {
venue = v;
},
$get: function() {
return {
getVenue: function() {
return venue;
}
};
}
};
});
app.config(function(gameProviderProvider) {
gameProviderProvider.setVenue('Angular Arena');
});
app.controller('TeamCtrl', function($scope, MAX_PLAYERS, teamName, PlayerFactory, CoachService, gameProvider) {
$scope.teamName = teamName;
$scope.maxPlayers = MAX_PLAYERS;
$scope.players = PlayerFactory.getPlayers();
$scope.coachMotivation = CoachService.motivate();
$scope.gameVenue = gameProvider.getVenue();
$scope.addPlayer = function(playerName) {
if ($scope.players.length < MAX_PLAYERS) {
PlayerFactory.addPlayer(playerName);
$scope.playerName = '';
} else {
alert('Team is full!');
}
};
});
输出
当你运行这个应用程序时,你将拥有一个功能完整的篮球队伍管理器。你可以向你的队伍添加球员(直到达到允许的最大数量),查看教练的激励语句,以及知道比赛在哪里进行。
以下是我们所涵盖的不同类型依赖注入的总结表格:
类型 | 描述 | 用例 |
---|---|---|
值 (Value) | 简单值注入 | 用于注入简单值 |
工厂 (Factory) | 返回一个对象 | 用于创建具有复杂逻辑的服务 |
服务 (Service) | 返回一个函数的实例 | 用于单例服务 |
提供者 (Provider) | 可配置的服务工厂 | 用于运行前需要配置的服务 |
常量 (Constant) | 不可变的值,可在配置中注入 | 用于应用程序范围内的常量值 |
记住,掌握依赖注入的关键是练习。从简单的注入开始,然后逐渐过渡到更复杂的场景。在你意识到之前,你将能够像专业人士一样创建模块化、可维护的AngularJS应用程序!
祝编码愉快,未来的AngularJS大师们!
Credits: Image by storyset