asp.net core后端+element ui tree樹控件基本用法


最近前后端分離大行其道,苦了后端人員,需要學習的東西還不少。於是到網上看了看前端的教程。沒想到前端發展到今天變得如此復雜。前端也包括權限和路由的東西。不過整體看上去似曾相識,只是需要熟悉些新的語法。昨天晚上試用了一下element ui。感覺這個框架還是不錯的。學了vue,再也不想用jQuery了。不再直接操作dom,而是跟數據打交道。今后打算好好學習下vue,網上做出來的后端框架還是不少的。下面就記錄以下element做前端,asp.net core做后端實現的一個樹控件。

后端

  1. 首先涉及到樹型結構,先上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;
        }
    }
}

  1. asp.net core比較省事,有了模型就可以直接生成增刪改查頁面和api。在visual studio中的Controllers文件夾上右鍵,選擇添加->“新搭建的基架項目",選擇如下圖,再選擇MaterialType作為模型,添加TreeDemoContext,做數據庫上下文類。就可以直接生成增刪改查頁面。
    在這里插入圖片描述
  2. 數據庫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);
    }

}
  1. 生成的創建頁面(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");}
}

  1. 增刪改查頁面好了,通過頁面添加幾個示例數據:
    在這里插入圖片描述

  2. 在按照步驟二,生成MaterialType的增刪改查api。

  3. 替換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. 配置跨域配置:
    (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
  1. 安裝element 和axios
npm install element-ui -S
npm install axios --save
  1. 再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")
  1. 在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>

  1. 運行:后端在visual studio中按ctrl+F5運行,前端在vscode終端中輸入npm run serve運行,運行效果:在這里插入圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM