一、理解和安装 AngularJs
1、AngularJS简介AngularJS是由Google的一个团队开发的JavaScript框架。
该团队创建了一个可扩展、可测试的框架,而且功能非常强大,直接数据绑定、服务器间通信、视图管理、历史管理、定位、验证等。
Angular都是关于JavaScript和HTML
3、入门
4、向网站中添加AngularJS
在NuGet包管理控制台执行Install-Package AngularJS.core 或 解决方案NuGet程序包搜索 “AngularJS” 安装。
@section scripts{
<script src="~/Scripts/angular.js"></script>
}
@*
<div ng-app>
{{2+3}}
</div>
*@
@*HTML5规范要求所有的用户自定义属性以"data-"开头,所以data-ng-app是符合HTML5规范的写法。*@
<div ng-app>
{{true?"true":"false"}}
</div>
输出结果:5
输出结果:true
注意:注释一个,另一个才能显示true
@*
Angular核心指令都是一个“ng”前缀
ng-app告知Angular跳入并初始化应用程序,并寻找其他内部指令和模板来控制DOM节,这一过程通常被称作编译DOM。
{{}} 双花括号是HTML模板
*@
5、数据库设置
在NuGet包管理控制台执行Install-Package EntityFramework 或 解决方案NuGet程序包搜索 “EntityFramework” 安装。
Model文件夹下创建Movie.cs
/// <summary>
/// 存储数据库中的数据
/// </summary>
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
public int ReleaseYear { get; set; }
public int Runtime { get; set; }
}Model文件夹下创建MovieDb.cs
/// <summary>
/// 添加一个DbSet类型的属性来实现对电影对象的添加、删除和查询
/// </summary>
public class MovieDb:DbContext
{
public DbSet<Movie> Movies { get; set; }
}控制台执行
Enable-Migrations(数据库上使用迁移)
迁移会在项目中创建Migrations文件,并创建Configuration.cs文件,会拥有一个Seed方法类。添加方法。
internal sealed class Configuration : DbMigrationsConfiguration<WebApplication2.Models.MovieDb>
{
public Configuration()
{
//程序包管理控制台执行 Enable-Migrations 迁移
//启动自动迁移
AutomaticMigrationsEnabled = true;
}
protected override void Seed(WebApplication2.Models.MovieDb context)
{
context.Movies.AddOrUpdate(m => m.Title,new Movie
{
Title = "Star Wars",ReleaseYear = 1977,Runtime = 121
},new Movie
{
Title = "Inception",ReleaseYear = 2010,Runtime = 148
},new Movie
{
Title = "Toy Story",ReleaseYear = 1995,Runtime = 81
}
);
}
}
命令执行 update-database命令创建数据库。
二、创建Web API
1、Controllers中添加MovieController
2、运行应用程序,浏览器导航到/api/movie。可以看到电影信息编码成XML或JSon
三、创建应用程序和模块
1、Views/Home/Index.cshtml
@section scripts{
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-route.js"></script>@*angular路由*@
<script src="~/Client/Scripts/atTheMovies.js"></script>
<script src="~/Client/Scripts/ListController.js"></script>
<script src="~/Client/Scripts/DetailsController.js"></script>
<script src="~/Client/Scripts/movieService.js"></script>
<script src="~/Client/Scripts/EditController.js"></script>
}
@*指示Angular把atTheMovies作为应用程序模块加载*@
<div data-ng-app="atTheMovies">
@*ng-view指令是一个占位符,Angular用它来插入当前视图*@
<ng-view></ng-view>
</div>
2、结构:
3、JS脚本
atTheMovies.js
angular路由需要在Index.cshtml 添加引用angular-route.js
//变量angular是全局Angular对象。
//和jQuery API通过全局变量$获取一样,Angular通过变量angular来访问顶级API.
//模块函数创建了一个新模块 atTheMovies,然而第2个参数即空数组
(function () {
//angular路由:ngRoute 路由名称
var app = angular.module("atTheMovies",["ngRoute"]);
var config = function ($routeProvider) {
$routeProvider.when("/list",{ templateUrl: "/client/views/list.html" })
.when("/details/:id",{ templateUrl: "/client/views/details.html" })
.otherwise({ redirectTo: "/list" });
};
//使用应用程序模块的config方法描述想让Angular处理的路由。
//通过ngRoute模块提供的$routeProvider组件实现路由描述。
app.config(config);
//使用constant方法注册常量值(第1个参数作key,第2个参数作为与key关联的值)。
//任何需要调用MovieController的组件现在可以请求movieApiUrl依赖,但只有movieService需要它。
app.constant("movieApiUrl","/api/movie/");
}());
movieService.js
//自定义$http服务
//服务是通过提供检索电影列表的方法模拟MovieController的服务器API
//通过ID获取、更新、创建和删除电影信息。
(function (app) {
var movieService = function ($http,movieApiUrl) {
var getAll = function () { return $http.get(movieApiUrl); };
var getById = function (id) { return $http.get(movieApiUrl + id); };
var update = function (movie) { return $http.put(movieApiUrl + movie.id,movie); };
var create = function (movie) { return $http.post(movieApiUrl,movie) };
var destroy = function (movie) { return $http.delete(movieApiUrl + movie.id) };
return {
getAll: getAll,getById: getById,update: update,create: create,delete:destroy
};
};
app.factory("movieService",movieService);
}(angular.module("atTheMovies")))
ListController.js
//引用了前面脚本中创建的atTheMovies模块。
//这样在函数中就可以通过变量app来访问atTheMovies模块
(function (app) {
//定义了ListController函数,首字母大写
//$scope变量是Angular构建的对象,它作为参数传递给了控制器函数。
//控制器负责初始化$scope中的数据和行为,因为$scope最后是有视图使用模型对象。
//通过向$scope对象添加message特性,视图就可以通过引用消息的模块使用控制器构建模型。
//var ListController = function ($scope) {
// $scope.message = "Hello,World!";
//};
//当控制器或其他组件需要使用服务时,会向Angular请求服务引用,并把服务作为参数传递给控制器或组件的注册函数,比如ListController函数。
//参数:$http 与服务器上的WebAPI端点进行通信。
//当$http服务作为参数传递给控制器之后,通过HTTP GET调用Web API终端,控制器就可以使用$http服务从服务器检索电影。
var ListController = function($scope,movieService) {
movieService.getall()
.success(function (data) {
$scope.movies = data;
});
//$scope的delete方法,delete方法可以通过ng-click指令调用。
//从理论上讲,delete方法首先使用movieService调用服务器,然后删除电影。
//只有当调用服务器成功后,delete方法才去调用removeMovieById函数来删除电影
$scope.delete = function (movie) {
movieService.delete(movie)
.success(function () {
removeMovieById(movie.Id);
});
};
var removeMovieById = function (id) {
for (var i = 0; i < $scope.movies.length; i++) {
if ($scope.movies[i].Id == id) {
$scope.movie.splice(i,1);
break;
}
}
};
$scope.create = function () {
$scope.edit = { movie: { title: "",runtime: 0,releaseYear: 0 } };
};
};
//使用组件需要的依赖的名称来注解组件
//ListController.$inject = ["$scope","$http"];
//Angular调用控制器方法来进行控制器构造函数注册
//控制器方法的第1个参数的控制器名称,Angular使用这个名称来查找控制器。
//第2个参数是与这个名称关联的构造函数。
app.controller("ListController",ListController)
}(angular.module("atTheMovies")));
//方法二:获取atTheMovies的引用
//(function (app) {
// var app = angular.module("atTheMovies");
//}());
DetailsController.js
(function (app) {
var DetailsController = function ($scope,$routeParams,movieService) {
var id=$routeParams.id;
movieService.getById(id)
.then(function (result) {
$scope.movie = result.data;
});
$scope.edit = function () {
$scope.edit.movie = angular.copy($scope.movie);
};
};
app.controller("DetailsController",DetailsController)
}(angular.module("atTheMovies")));
EditController.js
(function (app) {
var EditController = function ($scope,movieService) {
var updateMovie = function () {
movieService.update($scope.edit.movie)
.success(function () {
angular.extend($scope.movie,$scope.edit.movie);
$scope.edit.movie = null;
});
};
var createMovie = function () {
movieService.create($scope.edit.movie)
.success(function (movie) {
$scope.movies.push(movie);
$scope.edit.movie = null;
});
};
$scope.isEditable = function () {
return $scope.edit && $scope.edit.movie;
};
$scope.cancel = function () {
$scope.edit.movie = null;
};
$scope.save = function () {
if ($scope.edit.movie.id) {
updateMovie();
} else {
createMovie();
}
};
};
EditController.$inject = ["$scope","movieService"];
app.controller("EditController",EditController);
}(angular.module("AtTheMovies")));
4、Html
list.html
<!--
ng-controller指令把ListController(js文件名)添加到应用程序的一个div中
Angular 通过控制器名称来查找控制器,创建控制器。
通过添加Angular模板到标记语言,就可以看到控制器、视图、模型
-->
<div ng-controller="ListController">
<!--
{{message}}
{{movies.length}}
-->
<table>
<!--ng-repeat指令和js中for循环类似.-->
<tr ng-repeat="movie in movies">
<td>{{movie.Title}}</td>
<td>
<a href="#/details/{{movie.Id}}">详细</a>
<button class="btn btn-default" ng-click="delete(movie)">
删除
</button></td>
</tr>
</table>
<button class="btn" ng-click="create()">Create</button>
<div class="span6">
<div>
<!-- ng-include 指令包含编辑视图 -->
<div ng-include="'/Client/views/edit.html'"></div>
</div>
</div>
</div>
edit.html
<div ng-controller="EditController">
<!-- ng-show指令基于提供的表达式隐藏或展示DOM节
只有当模型isEditable函数返回true时,表单元素才会展示
-->
<fieldset ng-show="isEditable()">
<label for="title">
Title
</label>
<!--ng-model指令在模型和表单元素之间设置双向数据绑定-->
<input id="title" type="text" ng-model="edit.movie.title" required />
<label for="release">
Release Year
</label>
<input id="release" type="number" ng-model="edit.movie.releaseYear" required min="1900" max="2030" />
<label for="runtime">
Length
</label>
<input id="runtime" type="number" ng-model="edit.movie.runtime" required min="0" max="500" />
<button ng-click="save()">Save</button>
<button ng-click="cancel()">Cancel</button>
</fieldset>
</div>
details.html
<div ng-controller="DetailsController">
<h2>{{movie.Title}}</h2>
<div>Released in {{movie.ReleaseYear}}.</div>
<div>
{{movie.Runtime}}minutes long.
</div>
<button ng-click="edit()">Edit</button>
<div class="span6">
<div>
<div ng-include="'/Client/views/edit.html'"></div>
</div>
</div>
</div>