ASP.NET Web API 入门实战(3)--Vue.js创建单页应用

前面两节内容我们介绍了如何构建基于ASP.NET Web API的REST风格的服务,虽然demo比较简单,,而且仅仅建了一张数据表,没有涉及较多多的数据表映射关系,但是对于初学者来说这样给入门提供了一个整体思路,先易后难,慢慢上手,毕竟知易行难。

今天这篇文章主要是在前面已经构建好Web API 服务的基础上,介绍下如何使用当下较火的Vue.js来解析Web API,编写一个小界面,完成从后端API到前端展示数据的一个整体demo。

什么是Vue.js

Vue.js 是用于构建交互式的 Web 界面的库。
Vue.js 提供了 MVVM 数据绑定和一个可组合的组件系统,具有简单、灵活的 API,让编写动态的UI界面变得轻松简单。

Vue.js 特点

  • 简洁: HTML 模板 + JSON 数据,再创建一个 Vue 实例,就这么简单。
  • 数据驱动: 自动追踪依赖的模板表达式和计算属性。
  • 组件化: 用解耦、可复用的组件来构造界面。
  • 轻量: ~24kb min+gzip,无依赖。
  • 快速: 精确有效的异步批量 DOM 更新。
  • 模块友好: 通过 NPM 或 Bower 安装,无缝融入你的工作流。

Vue.js 安装

这里我们只介绍使用<script>标签引入,NPM安装和Bower安装小伙伴们可以参考网上的教程。
1.引用方法一:
直接下载并用 <script> 标签引入,Vue 会被注册为一个全局变量。
Vue.js 官网下载地址:http://vuejs.org/guide/installation.html
在我们的demo中引用如下:

1
<script src="~/Scripts/vue.js"></script>

2.引用方法二:
使用其静态资源 CDN 库,在我们的demo中引用如下:

1
<script src="http://cdnjs.cloudflare.com/ajax/libs/vue/1.0.7/vue.min.js"></script>

什么是vue-resource

vue-resource是Vue.js的一款插件,它可以通过XMLHttpRequest或JSONP发起请求并处理响应。

vue-resource特点

vue-resource插件具有以下特点:

  • 体积小:vue-resource非常小巧,在压缩以后只有大约12KB,服务端启用gzip压缩后只有4.5KB大小,这远比jQuery的体积要小得多。
  • 支持主流的浏览器:和Vue.js一样,vue-resource除了不支持IE 9以下的浏览器,其他主流的浏览器都支持。
  • 支持拦截器:拦截器是全局的,拦截器可以在请求发送前和发送请求后做一些处理。
    拦截器在一些场景下会非常有用,比如请求发送前在headers中设置access_token,或者在请求失败时,提供共通的处理方式。

引入vue-resource

同Vue.js的引用一样,有两种引入方法:
1.引用方法一:
在我们的demo中引用如下:

1
<script src="~/Scripts/vue-resource.js"></script>

2.引用方法二:
使用其静态资源 CDN 库,在我们的demo中引用如下:

1
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-resource/0.1.17/vue-resource.js"></script>

基本语法

引入vue-resource后,可以基于全局的Vue对象使用http,也可以基于某个Vue实例使用http。

1
2
3
4
5
6
7
// 基于全局Vue对象使用http
Vue.http.get('/someUrl', [options]).then(successCallback, errorCallback);
Vue.http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);

// 在一个Vue实例内使用$http
this.$http.get('/someUrl', [options]).then(successCallback, errorCallback);
this.$http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);

上述的then方法的回调函数也有两种写法,第一种是传统的函数写法,第二种是更为简洁的ES 6的Lambda写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 传统写法
this.$http.get('/someUrl', [options]).then(function(response){
// 响应成功回调
}, function(response){
// 响应错误回调
});


// Lambda写法
this.$http.get('/someUrl', [options]).then((response) => {
// 响应成功回调
}, (response) => {
// 响应错误回调
});

在本demo中使用第二种Lambda写法总是报语法错误,所以仍然采用的是传统写法

下面开始我们本demo前端界面构建的具体介绍。最终完成的效果如下图所示:

Views结构

WebAPIDemo项目的Views文件夹中,我们可以看到有Home文件夹、Shared文件夹、_ViewStart.cshtml文件,其中,Home文件夹放置网站主页文件,Shared文件夹放置模板文件,_ViewStart.cshtml进行初始化。

在demo中使用的前端框架是BootStrap,这里我们将使用Shared文件夹下的模板文件,因此我们在Home文件夹下的html代码只需要写body部分;当然了,如果你不想使用模板文件,需要引入如下代码:

1
2
3
@{
Layout = null;
}

引入js文件

我们本次demo做一个单页界面作为主页,因此需要在Home文件下的Index.cshtml进行代码的编写,现在我们把Index.cshtml下的代码清空。

首先引入js文件,这里我用CDN库的方式引入。需要注意的是引用版本问题,我发现这是一个大坑啊,引用版本不一样导致编译直接出错,所以大家可以采用下面的应用方法:

1
2
<script src="http://cdnjs.cloudflare.com/ajax/libs/vue/1.0.7/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-resource/0.1.17/vue-resource.js"></script>

编写html代码

在demo中我们实现的是取回Web API返回的值以表格的方式进行展示,同时能够进行添加和删除操作,具体实现的是StudentController.cs中的getpostdelete方法。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<div class="container">
<div class="col-md-6 col-md-offset-3">
<h1>Vue.js demo</h1>
<div id="app">
<table class="table table-hover" v-cloak>
<thead>
<tr>
<th class="text-center">姓名</th>
<th class="text-center">学号</th>
<th class="text-center">班级</th>
<th class="text-center">电话</th>
<th class="text-center">操作</th>
</tr>
</thead>
<tbody>
<tr v-for="student in students ">
<td class="text-center">{{student.Name}}</td>
<td class="text-center">{{student.StuID}}</td>
<td class="text-center">{{student.Class}}</td>
<td class="text-center">{{student.Phone}}</td>
<td class="text-center">
<button type="button" class="btn btn-danger" v-on:click="deleteStudent(student)">删除</button>
</td>

</tr>
</tbody>
</table>

<legend>添加学生信息:{{ stu.Name }}</legend>
<div v-show="stu.ID" class="form-group">
<label>ID</label>
<input type="text" v-model="stu.ID" disabled="disabled" />
</div>
<div class="form-group">
<label for="">姓名</label>
<input type="text" class="form-control" v-model="stu.Name">
</div>
<div class="form-group">
<label for="">学号</label>
<input type="text" class="form-control" v-model="stu.StuID">
</div>
<div class="form-group">
<label for="">班级</label>
<input type="text" class="form-control" v-model="stu.Class">
</div>
<div class="form-group">
<label for="">电话</label>
<input type="text" class="form-control" v-model="stu.Phone">
</div>
<button class="btn btn-primary btn-block" v-on:click="createStudent(student)">添加</button>
</div>


</div>
</div>

编写js代码

vue-resource的请求API是按照REST风格设计的,它提供了7种请求API:

  • get(url, [options])
  • head(url, [options])
  • delete(url, [options])
  • jsonp(url, [options])
  • post(url, [body], [options])
  • put(url, [body], [options])
  • patch(url, [body], [options])

除了jsonp以外,另外6种的API名称是标准的HTTP方法。当服务端使用REST API时,客户端的编码风格和服务端的编码风格近乎一致,这可以减少前端和后端开发人员的沟通成本。
本demojs代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<script>
Vue.http.options.emulateJSON = true;
var demo = new Vue({
el: '#app',
data: {
student: [{
name: 'ID',
isKey: true
}, {
name: 'Name'
}, {
name: 'StuID'
}, {
name: 'Class'
}, {
name: 'Phone'
}],
students: [],

apiUrl: 'http://localhost:7874/api/students',
stu: {}
},
ready: function() {
this.getStudents()
},
methods: {
getStudents: function () {
this.$http.get(this.apiUrl, function (data) {
this.$set('students', data);
})
},
createStudent: function() {
var vm = this
vm.$http.post(vm.apiUrl, vm.stu)
.then(function(response) {
vm.$set('stu', {})
vm.getStudents()
})
},
deleteStudent: function(student){
var vm = this
vm.$http.delete(this.apiUrl + '/' + student.ID)
.then(function(response) {
vm.getStudents()
})
}
}
})
</script>

ok,至此代码已经写完了,运行查看一下效果,可以实现我们所需的功能。

双向数据绑定

最后我们简单说一下数据绑定,在上面的代码中,有如下代码:

1
2
3
4
5
6
7
8
9
<legend>添加学生信息:{{ stu.Name }}</legend>
<div v-show="stu.ID" class="form-group">
<label>ID</label>
<input type="text" v-model="stu.ID" disabled="disabled" />
</div>
<div class="form-group">
<label for="">姓名</label>
<input type="text" class="form-control" v-model="stu.Name">
</div>

使用v-model这个指令完成中间的底层逻辑,实现绑定的效果。改变其中的任何一层,另外一层都会改变。

以上实例中 会根据输入框 input(标签为“姓名”) 的改变而改变(v-model=”stu.Name”)。

ok,本入门系列暂且告一段落,大家多多参考网上大牛的博客,只有自己趟过的坑才会牢牢记住,知道自己如何避免踩到同样的坑。

ASP.NET Web API 入门实战系列:

  1. ASP.NET Web API 入门实战(1)–开篇
  2. ASP.NET Web API 入门实战(2)–处理数据
  3. ASP.NET Web API 入门实战(3)–Vue.js创建单页应用程序

本demo源码已上传到Github:WebAPIDemo-Vuejs

坚持原创技术分享,您的支持将鼓励我继续创作!