前言
遇到这个问题,是由于自己在mvc项目中使用vue而并不想jquery(人嘛,就是要折腾),并且表单中的一个属性是一个集合。
研究了下Razor如何实现的,用jquery感觉就挺麻烦了,vue用在数据绑定方面好强好方便,灵活运用后感觉很棒。
Razor模板的确强大,TagHelper书写太爽快了,但是数据修改后的更新需要在前端利用jquery进行修改,感觉挺可惜的,不知道有没有更方便的。
Razor是如何实现
首先我们简单定义一下结构
1 public class Movie 2 { 3 public int Id { get; set; } 4 public string Name { get; set; } 5 public List<Pseron> Persons { get; set; } = new List<Pseron>(); 6 } 7 public class Pseron 8 { 9 public int Id { get; set; } 10 public string Name { get; set; } 11 public int Age { get; set; } 12 }
接着创建一个Action
1 public IActionResult List() 2 { 3 Movie movie = new Movie(); 4 movie.Id = 123; 5 movie.Name = "猫和老鼠"; 6 movie.Persons.Add(new Pseron { Id = 456, Name = "Tom", Age = 18 }); 7 movie.Persons.Add(new Pseron { Id = 789, Name = "Jecky", Age = 20 }); 8 return View(movie); 9 }
然后我们在视图里简单的显示一下
1 @model Movie 2 3 <form asp-action="List"> 4 <div class="form-group"> 5 <label asp-for="Id"></label> 6 <input class="form-control" asp-for="Id" /> 7 </div> 8 <div class="form-group"> 9 <label asp-for="Name"></label> 10 <input class="form-control" asp-for="Name" /> 11 </div> 12 <table class="table"> 13 <thead> 14 <tr> 15 <td>序号</td> 16 <td>Id</td> 17 <td>Name</td> 18 <td>Age</td> 19 </tr> 20 </thead> 21 <tbody> 22 @for (int i = 0; i < Model.Persons.Count; i++) 23 { 24 <tr> 25 <td>@(i + 1)</td> 26 <td><input class="form-control" asp-for="Persons[i].Id" /></td> 27 <td><input class="form-control" asp-for="Persons[i].Name" /></td> 28 <td><input class="form-control" asp-for="Persons[i].Age" /></td> 29 </tr> 30 } 31 </tbody> 32 </table> 33 </form>
最后我们查看下结果
观察结论
众所周知,提交form时依据的是name属性,Razor模板渲染的时候,按照 “ 属性[索引].属性 ”的形式作为name赋值,那么我们只要依样画葫芦就可以了。
需要注意的是,索引必须从0开始,且索引应该连续。这时候就觉得用jQuery去控制增删就麻烦很多。vue在这个时候有一点点小方便。
让我们看看如何用vue去实现
同样的我们建立一个Action(偷懒,没建HttpPost请求),这里我们需要将数据转换为json字符串,然后在视图里再转换为json让vue去渲染
1 public IActionResult ListVue(Movie movie) 2 { 3 movie = movie ?? new Movie(); 4 ViewData["Data"] = System.Text.Json.JsonSerializer.Serialize(movie); 5 return View(); 6 }
然后建立一个视图并用vue去渲染数据,这里用了@Html.Raw()处理了一下字符串,不然双引号会被处理成转义字符。
添加新行的只需要向数组中插入一个对象就完成了,而且索引只需要vue去管理就可以了,体验一级棒!!!
删行也非常简单!!!
1 @{ 2 var Data = ViewData["Data"].ToString(); 3 } 4 5 <div id="app"> 6 <form asp-action="ListVue"> 7 <div class="form-group"> 8 <label>Id</label> 9 <input class="form-control" name="Id" v-model="movie.Id" /> 10 </div> 11 <div class="form-group"> 12 <label>Name</label> 13 <input class="form-control" name="Name" v-model="movie.Name" /> 14 </div> 15 <a href="javascript:void(0)" class="btn btn-primary mb-1" @@click="NewRow()">插入新行</a> 16 <table class="table"> 17 <thead> 18 <tr> 19 <td>序号</td> 20 <td>Id</td> 21 <td>Name</td> 22 <td>Age</td> 23 </tr> 24 </thead> 25 <tbody> 26 <tr v-for="(item, index) in movie.Persons"> 27 <td>{{ index + 1 }}</td> 28 <td><input class="form-control" :name="'Persons['+index+'].Id'" v-model="item.Id" /></td> 29 <td><input class="form-control" :name="'Persons['+index+'].Name'" v-model="item.Name" /></td> 30 <td><input class="form-control" :name="'Persons['+index+'].Age'" v-model="item.Age" /></td> 31 </tr> 32 </tbody> 33 </table> 34 <button type="submit" class="btn btn-primary">提交</button> 35 </form> 36 37 </div> 38 39 @section Scripts{ 40 <script> 41 var vm = new Vue({ 42 el: '#app', 43 data: { 44 movie: JSON.parse('@Html.Raw(Data)') 45 }, 46 methods: { 47 NewRow() { 48 this.movie.Persons.push([]); 49 } 50 } 51 }) 52 </script> 53 }
我们看看是怎样的界面
我们再去跟踪下前后端都发生了什么。
总结
vue的绑定功能真的是太方便了,不知道Razor有没有办法实现类似的功能。用jQuery又觉得麻烦了。