ASP .Net Core MVC如何利用vue提交包含List属性的form表单

时间:2024-01-26 07:19:22

前言

遇到这个问题,是由于自己在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又觉得麻烦了。