来源: Vue在ASP.NET MVC中的进行前后端的交互 – Kaden – 博客园
Preface:
由于最近在研究前端相关的技术,作为前端非常优秀的框架Vue,个人在学习的过程中遇到一些问题,网上相关资料有限,所以在这这里总结一下个人使用Vue的一点经验,以便后来者借鉴!
官方文档:Vue.js
使用Vue在ASP.NET MVC中进行前后端交互
在阅读下面的文章之前你需要先了解一下Vue官方推荐的前后端交互的插件:
1.resource(官方在2.0版本之后取消了对此插件的维护)
2.axios
注:这里使用的都是异步的插件,因为这样才会在你的项目中具有使用意义,当然你也可以用其它的js库,如JQuery、Fetch等等…
Instance:
Controller
1 using Demo.Models; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Web; 6 using System.Web.Mvc; 7 8 namespace Demo.Controllers 9 { 10 //[RoutePrefix("api/Goods")] 11 public class GoodsController : Controller 12 { 13 List<GoodsEntity> goosdList = new List<GoodsEntity> 14 { 15 new GoodsEntity(){ ID=001,Name="水",Type=1,Price=3}, 16 new GoodsEntity(){ ID=002,Name="牛奶",Type=1,Price=10}, 17 new GoodsEntity(){ ID=003,Name="面包",Type=2,Price=15} 18 }; 19 20 // GET: Goods 21 public ActionResult Index() 22 { 23 return View(); 24 } 25 26 public ActionResult Check() 27 { 28 return View(); 29 } 30 31 [HttpGet] 32 public JsonResult GetGoodsType() 33 { 34 List<int> goodsType = new List<int>(); 35 foreach (var item in goosdList) 36 { 37 if (!goodsType.Contains(item.Type)) 38 { 39 goodsType.Add(item.Type); 40 } 41 } 42 return Json(goodsType, JsonRequestBehavior.AllowGet); 43 } 44 45 [HttpGet] 46 public JsonResult GetAllGoods() 47 { 48 return Json(goosdList, JsonRequestBehavior.AllowGet); 49 } 50 51 [HttpPost] 52 public JsonResult GetGoods(int id) 53 { 54 var entity = goosdList.Where(g => g.ID == id).FirstOrDefault(); 55 if (entity != null) 56 { 57 return Json(new ReturnJsonInfo(500, "success!", entity)); 58 } 59 return Json(new ReturnJsonInfo(400, "error!", null)); 60 } 61 62 [HttpPost] 63 public JsonResult UpdateGoods(GoodsEntity entity) 64 { 65 if (entity!=null) 66 { 67 var goodsEntiy = goosdList.FirstOrDefault(g => g.ID == entity.ID); 68 if (goodsEntiy!=null) 69 { 70 goodsEntiy = entity; 71 return Json(new ReturnJsonInfo(500, "success!", goosdList)); 72 } 73 goosdList.Add(entity); 74 return Json(new ReturnJsonInfo(500, "success!", goosdList)); 75 } 76 return Json(new ReturnJsonInfo(400, "error!",null)); 77 } 78 79 [HttpPost] 80 public JsonResult DelectGoods(int id) 81 { 82 var entity = goosdList.Where(g => g.ID == id).FirstOrDefault(); 83 if (entity != null) 84 { 85 goosdList.Remove(entity); 86 return Json(new ReturnJsonInfo(500, "success!", goosdList)); 87 } 88 return Json(new ReturnJsonInfo(400, "error!",null)); 89 } 90 91 } 92 }
在上面的控制器中加载了一些示例数据,并且都是以json的格式返回前端,这样前端就可以直接使用这些数据。
注:控制器返回至前端的json中,上面使用 “ReturnJsonInfo” 对象序列化进行返回, “ReturnJsonInfo” 代码如下。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 6 namespace Demo.Models 7 { 8 public class ReturnJsonInfo 9 { 10 public int Code { get; set; } 11 public string Message { get; set; } 12 public object Entity { get; set; } 13 public ReturnJsonInfo(int code, string message,object obj) 14 { 15 this.Code = code; 16 this.Message = message; 17 this.Entity = obj; 18 } 19 } 20 }
View
1.前端采用resource插件
1 @{ 2 ViewBag.Title = "Goods IndexPage"; 3 } 4 <script type="text/javascript" src="~/Resources/Scripts/vue.js"></script> 5 <script type="text/javascript" src="~/Resources/Scripts/vue-resource.js"></script> 6 <h2>Index</h2> 7 <div id="demo"> 8 <table> 9 <tr> 10 <td><label>编号:</label></td> 11 <td><input type="text" v-model="newGoods.id" /></td> 12 13 <td><label>名称:</label></td> 14 <td><input type="text" v-model="newGoods.name" /></td> 15 16 <td><label>类型:</label></td> 17 <td><input type="text" v-model="newGoods.type" /></td> 18 19 <td><label>售价:</label></td> 20 <td><input type="text" v-model="newGoods.price" /></td> 21 22 <td><input type="submit" value="查询" v-on:click="GetGoods(newGoods.id)" /></td> 23 </tr> 24 </table> 25 <table v-show="goodsList.length"> 26 <tr> 27 <td>编号</td> 28 <td>名称</td> 29 <td>类型</td> 30 <td>售价</td> 31 </tr> 32 <tr v-for="item in goodsList"> 33 <td>{{item.ID}}</td> 34 <td>{{item.Name}}</td> 35 <td>{{item.Type}}</td> 36 <td>{{item.Price}}</td> 37 </tr> 38 </table> 39 </div> 40 <script type="text/javascript"> 41 var view = new Vue( 42 { 43 el: "#demo", 44 data: { 45 goodsList: [], 46 newGoods: {id:'',name:'',type:'',price:''} 47 }, 48 created: function () { 49 this.InIt(); 50 }, 51 methods: { 52 InIt: function () { 53 //初始化 54 this.GetAllGoods(); 55 }, 56 GetAllGoods: function () { 57 var _self = this; 58 _self.$http.get("../Goods/GetAllGoods").then( 59 // Lambda写法 60 (response) => { 61 //successCallback 62 for (var i = 0; i < response.data.length; i++) { 63 _self.goodsList.push(response.data[i]); 64 } 65 } , 66 (response) => { 67 //errorCallback 68 } 69 ); 70 }, 71 GetGoods: function (_id) { 72 var _self = this; 73 _self.goodsList = []; 74 if (_id.length > 0) { 75 _self.$http.post("../Goods/GetGoods", { id: _id }).then( 76 // 传统写法 77 function (response) { 78 //successCallback 79 if (response.data.Code == 500) { 80 _self.goodsList.push(response.data.Entity); 81 } 82 else { 83 alert(response.data.Message); 84 } 85 }, 86 function (response) { 87 //errorCallback 88 } 89 ) 90 .catch(function (response) { 91 console.log(response); 92 }); 93 } 94 else { 95 _self.GetAllGoods(); 96 } 97 } 98 } 99 } 100 ); 101 </script>
2.前端采用axios插件
1 @{ 2 Layout = null; 3 } 4 5 <!DOCTYPE html> 6 7 <html> 8 <head> 9 <meta name="viewport" content="width=device-width" /> 10 <title>Check</title> 11 <script type="text/javascript" src="~/Resources/Scripts/vue.js"></script> 12 <script type="text/javascript" src="~/Resources/Scripts/axios.min.js"></script> 13 </head> 14 <body> 15 <div id="demo"> 16 <div> 17 <table> 18 <tr> 19 <td><label>编号:</label></td> 20 <td><input type="text" v-model="newGoods.id" /></td> 21 22 <td><label>名称:</label></td> 23 <td><input type="text" v-model="newGoods.name" /></td> 24 25 <td><label>类型:</label></td> 26 <td> 27 <select v-model="newGoods.type"> 28 <option value="">---ALL---</option> 29 <option v-for="type in goodsType" v-bind:value="type">{{type}}</option> 30 </select> 31 </td> 32 33 <td><label>售价:</label></td> 34 <td><input type="text" v-model="newGoods.price" /></td> 35 36 <td> 37 <input type="submit" value="查询" v-on:click="GetGoods(newGoods.id)" /> 38 <input type="submit" value="更新" v-on:click="UpdateGoods(newGoods.id,newGoods.name,newGoods.type,newGoods.price)" /> 39 <input type="submit" value="删除" v-on:click="DelectGoods(newGoods.id)" /> 40 </td> 41 </tr> 42 </table> 43 </div> 44 <div> 45 <table v-show="goodsList.length"> 46 <tr> 47 <td>行号</td> 48 <td>编号</td> 49 <td>名称</td> 50 <td>类型</td> 51 <td>售价</td> 52 </tr> 53 <tr v-for="(item,index) in goodsList"> 54 <td>{{index+1}}</td> 55 <td>{{item.ID}}</td> 56 <td>{{item.Name}}</td> 57 <td>{{item.Type}}</td> 58 <td>{{item.Price}}</td> 59 </tr> 60 </table> 61 </div> 62 </div> 63 64 65 <script type="text/javascript"> 66 var vm = new Vue({ 67 el: "#demo", 68 data: { 69 goodsType:[], 70 goodsList: [], 71 newGoods: { id: '', name: '', type: '', price: '' } 72 }, 73 mounted() { 74 this.GetGoodsType(); 75 this.GetAllGoods(); 76 }, 77 methods: 78 { 79 GetGoodsType: function () { 80 axios.get("../Goods/GetGoodsType").then( 81 (response) => { 82 this.goodsType = []; 83 for (var i = 0; i < response.data.length; i++) { 84 this.goodsType.push(response.data[i]); 85 } 86 }, 87 (response) => { 88 alert(response.status); 89 } 90 ) 91 .catch(function (response) { 92 console.log(response); 93 }); 94 } , 95 GetAllGoods: function () { 96 axios.get('../Goods/GetAllGoods').then( 97 function (response) { 98 vm.goodsList = []; 99 for (var i = 0; i < response.data.length; i++) { 100 vm.goodsList.push(response.data[i]); 101 } 102 //vm.goodsList.splice(response.data.length); 103 }, 104 function (response) { 105 alert(response.status); 106 } 107 ) 108 .catch( 109 function (error) { 110 alert(error); 111 } 112 ) 113 }, 114 GetGoods: function (_id) { 115 if (_id.length > 0) { 116 axios.post("../Goods/GetGoods", { id: _id }).then( 117 (response) => { 118 this.goodsList = []; 119 if (response.data.Code == 500) { 120 this.goodsList.push(response.data.Entity); 121 } 122 else { 123 alert(response.data.Message); 124 } 125 126 }, 127 (response) => { 128 alert(response.status); 129 } 130 ) 131 .catch(function (response) { 132 console.log(response); 133 }); 134 } 135 else { 136 this.GetAllGoods(); 137 } 138 }, 139 UpdateGoods: function (_id,_name,_type,_price) { 140 axios.post("../Goods/UpdateGoods", { entity: { ID: _id, Name: _name, Type: _type, Price: _price } }).then( 141 (response) => { 142 this.goodsList = []; 143 if (response.data.Code == 500) { 144 for (var i = 0; i < response.data.Entity.length; i++) { 145 this.goodsList.push(response.data.Entity[i]); 146 } 147 } 148 else { 149 alert(response.data.Message); 150 } 151 }, 152 (response) => { 153 alert(response.status); 154 } 155 ) 156 .catch(function (response) { 157 console.log(response); 158 }); 159 }, 160 DelectGoods: function (_id) { 161 axios.post("../Goods/DelectGoods", { id: _id }).then( 162 (response) => { 163 this.goodsList = []; 164 if (response.data.Code == 500) { 165 for (var i = 0; i < response.data.Entity.length; i++) { 166 this.goodsList.push(response.data.Entity[i]); 167 } 168 } 169 else { 170 alert(response.data.Message); 171 } 172 173 }, 174 (response) => { 175 alert(response.status); 176 } 177 ) 178 .catch(function (response) { 179 console.log(response); 180 }); 181 } 182 }, 183 184 }); 185 </script> 186 </body> 187 </html>
在上面的视图中,前端都是用数组进行填充的,值得注意的是vue在数组监听这一块做得并不是特别友好。但也提供了一些非常友好的api。
如果你也采用上述方式更新view,请参阅vue官方提供的关于操作数组方法
Perorations:
在上面的Demo中,采用的是ASP.NET MVC模板。在写View部分的时候感觉确实比较方便,不需要再去写获取元素的代码,只需要把数据绑定至元素上,关注数据的变动就可以了。
当然你也可以选择Razor语法,只不过那样看起来并不是很友善。
以上是个人在写这个Demo之后的一些总结。如有描述不当,请@作者修改,谢谢!