asp.net core後端+element ui tree樹控制元件基本用法
阿新 • • 發佈:2020-12-23
最近前後端分離大行其道,苦了後端人員,需要學習的東西還不少。於是到網上看了看前端的教程。沒想到前端發展到今天變得如此複雜。前端也包括許可權和路由的東西。不過整體看上去似曾相識,只是需要熟悉些新的語法。昨天晚上試用了一下element ui。感覺這個框架還是不錯的。學了vue,再也不想用jQuery了。不再直接操作dom,而是跟資料打交道。今後打算好好學習下vue,網上做出來的後端框架還是不少的。下面就記錄以下element做前端,asp.net core做後端實現的一個樹控制元件。
後端
- 首先涉及到樹型結構,先上Model,這裡以材料型別為例,型別可以巢狀,有的有父類。型別為Material:
using Newtonsoft.Json; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; namespace TreeDemo.Models { /// <summary> /// 材料型別 /// </summary> public class MaterialType { /// <summary> /// id /// </summary> public int Id { get; set; } /// <summary> /// 材料型別名稱 /// </summary> [StringLength(50)] public string Title { get; set; } /// <summary> /// 父類Id /// </summary> public int? ParentId { get; set; } [JsonIgnore] [ForeignKey(nameof(ParentId))] public virtual MaterialType ParentType { get; set; } public virtual ICollection<MaterialType> MaterialTypes { get; set; } public static List<MaterialType> GetData(List<MaterialType> data) { var nodes = data.Where(x => x.ParentId == null).Select(x => new MaterialType { Id = x.Id, ParentId = x.ParentId, Title = x.Title }).ToList(); foreach (var item in nodes) { item.MaterialTypes = GetChildrens(item, data); } return nodes; } private static List<MaterialType> GetChildrens(MaterialType item, List<MaterialType> data) { var children = data.Where(x=>x.ParentId==item.Id).Select(x=> new MaterialType { Id = x.Id, ParentId = x.ParentId, Title = x.Title }).ToList(); foreach (var child in children) { child.MaterialTypes = GetChildrens(child, data); } return children; } } }
- asp.net core比較省事,有了模型就可以直接生成增刪改查頁面和api。在visual studio中的Controllers資料夾上右鍵,選擇新增->“新搭建的基架專案",選擇如下圖,再選擇MaterialType作為模型,新增TreeDemoContext,做資料庫上下文類。就可以直接生成增刪改查頁面。
- 資料庫ORM用的是Entity Framework Core。這裡需要再TreeDemoContext類中,配置以下表關係:
(樹形結構的關係配置可以參考我之前寫的一篇文章:
Entity Framework Core樹狀結構增刪改查)
using Microsoft.EntityFrameworkCore; using TreeDemo.Models; public class TreeDemoContext : DbContext { public TreeDemoContext(DbContextOptions<TreeDemoContext> options) : base(options) { } public DbSet<MaterialType> MaterialType { get; set; } //配置樹狀結構表關係 protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<MaterialType>() .HasMany(x => x.MaterialTypes) .WithOne(x => x.ParentType) .HasForeignKey(x => x.ParentId) .OnDelete(DeleteBehavior.ClientSetNull); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); } }
- 生成的建立頁面(create.cshtml)需要稍微修改以下,因為預設select選項為第一個,修改的目的是讓select一開始為空:
@model TreeDemo.Models.MaterialType
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>MaterialType</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ParentId" class="control-label"></label>
<select asp-for="ParentId" class="form-control" asp-items="ViewBag.ParentId">
<option value="">選擇父型別</option>
</select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
-
增刪改查頁面好了,通過頁面新增幾個示例資料:
-
在按照步驟二,生成MaterialType的增刪改查api。
-
替換System.Text.Json包,這裡通過nuget安Newtonsoft.Json和Microsoft.AspNetCore.Mvc.NewtonsoftJson包,在Startup中配置json格式。為啥配置:因為System.Text.Json不支援迴圈引用,樹中的children在序列化時,會引發迴圈引用錯誤。
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
//在ConfigureServices中新增
services.AddControllersWithViews().AddNewtonsoftJson(options=>
{
//忽略迴圈引用
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
//不使用駝峰樣式的key
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
//設定時間格式
options.SerializerSettings.DateFormatString = "yyyy-MM-dd";
});
- 配置跨域配置:
(1). 在appsettings.json中新增
"AppCores": "http://localhost:8080,http://localhost:8081",
(2) 在startup類的ConfigureService方法中配置跨域:
services.AddCors(options => options.AddPolicy("AllowAll", policy => policy.WithOrigins(cores).AllowAnyMethod().AllowAnyHeader().AllowCredentials()));
(3) 還需要再api的方法中啟用跨域:
[EnableCors("AllowAll")]
[HttpGet]
public async Task<ActionResult<IEnumerable<MaterialType>>> GetMaterialType()
{
return await _context.MaterialType.ToListAsync();
}
後端到此結束
前端
1.建立vue專案
vue create treedemo
- 安裝element 和axios
npm install element-ui -S
npm install axios --save
- 再main.js中引用element ui和axios
import Vue from "vue"
import App from "./App.vue"
import ElementUI from "element-ui"
import "element-ui/lib/theme-chalk/index.css"
import axios from "axios"
axios.defaults.baseURL = "https://localhost:44356"
Vue.use(ElementUI)
Vue.prototype.$http = axios
Vue.config.productionTip = false
new Vue({
render: h => h(App)
}).$mount("#app")
- 在App.vue中編寫頁面,替換原來的內容:
<template>
<div id="app">
<el-tree
:data="materialTypesData"
:props="{ children: 'MaterialTypes', label: 'Title' }"
@node-click="handleMaterialTypeNodeClick"
></el-tree>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
materialTypesData: []
}
},
mounted() {
this.getMaterialTypes()
},
methods: {
//遠端獲取資料
getMaterialTypes() {
this.$http
.get("https://localhost:44356/api/materialtypes/tree")
.then(res => {
console.log(res)
this.materialTypesData = res.data
})
},
//樹節點點選事件
handleMaterialTypeNodeClick(data) {
this.$message("test" + data)
}
}
}
</script>
<style></style>
- 執行:後端在visual studio中按ctrl+F5執行,前端在vscode終端中輸入
npm run serve
執行,執行效果: