家校通小程序實戰教程10部門管理前后端連接

目錄

  • 1 加載后端的數據
  • 2 為什么不直接給變量賦值
  • 3 保存部門信息
  • 4 最終的效果
  • 5 總結

現在部門管理已經完成了后端功能和前端開發,就需要在前端調用后端的數據完成界面的展示,而且在錄入部門信息后需要提交到數據庫里,本篇我們介紹一下前后端如何交互。

1 加載后端的數據

現在后端API已經有了,頁面加載的時候需要從后端讀取數據。打開應用,點擊編輯JSX代碼

在這里插入圖片描述
輸入如下代碼

export default function DepartmentTree(props: JSXCompProps) {const { $w, contentSlot1, style } = props;const { Modal, Input, Tree, Button, Form } = antd;const [treeData, setTreeData] = React.useState([]);const [selectedNode, setSelectedNode] = React.useState(null);const [addChildModalVisible, setAddChildModalVisible] = React.useState(false);const [newDepartmentName, setNewDepartmentName] = React.useState("");const [contextMenuTargetId, setContextMenuTargetId] = React.useState(null);const [contextMenuPosition, setContextMenuPosition] = React.useState(null);const [form] = Form.useForm();// 初始化獲取部門數據React.useEffect(() => {async function fetchDepartments() {try {const result = await $w.cloud.callDataSource({dataSourceName: "departmentManagement_adpurdw",methodName: "getAllDepartments",params: {}});if (result && result.data) {setTreeData(result.data);} else {Modal.warning({ title: "數據加載失敗", content: "未獲取到部門數據。" });}} catch (error) {console.error("Error fetching departments:", error);Modal.error({ title: "加載失敗", content: "獲取部門數據時出錯,請稍后重試。" });}}fetchDepartments();}, [$w]);// 點擊節點事件const handleNodeClick = (node) => {setSelectedNode(node);setContextMenuTargetId(null);form.setFieldsValue({ name: node.name });};// 切換節點展開/收起const toggleNode = (node) => {node.isOpen = !node.isOpen;setTreeData([...treeData]);};// 遞歸更新樹節點const updateTree = (nodes, callback) => {return nodes.map((node) => {if (callback(node)) {return { ...node };}if (node.children) {return { ...node, children: updateTree(node.children, callback) };}return node;});};// 添加子部門邏輯const handleAddChild = () => {if (!newDepartmentName.trim()) {return Modal.warning({title: "部門名稱不能為空",content: "請輸入部門名稱后重試。"});}const newChild = {id: Date.now(),name: newDepartmentName,parentId: contextMenuTargetId,children: [],isOpen: false};setTreeData((prevTreeData) =>updateTree(prevTreeData, (node) => {if (node.id === contextMenuTargetId) {node.children = [...(node.children || []), newChild];return true;}return false;}));setAddChildModalVisible(false);setNewDepartmentName("");};// 保存表單修改const handleSaveForm = () => {form.validateFields().then((values) => {setTreeData((prevTreeData) =>updateTree(prevTreeData, (node) => {if (node.id === selectedNode.id) {node.name = values.name;return true;}return false;}));Modal.success({ title: "保存成功", content: "部門信息已更新。" });}).catch((info) => console.error("Validate Failed:", info));};// 右鍵點擊事件const handleRightClick = (e, node) => {e.preventDefault();setContextMenuTargetId(node.id);setContextMenuPosition({ x: e.clientX, y: e.clientY });};// 渲染樹節點const renderTree = (nodes) =>nodes.map((node) => (<Tree.TreeNodekey={node.id}title={<spanonClick={() => handleNodeClick(node)}onContextMenu={(e) => handleRightClick(e, node)}>{node.name}</span>}>{node.children && renderTree(node.children)}</Tree.TreeNode>));return (<div style={{ display: "flex", ...style }}>{/* 左側樹 */}<divstyle={{flex: "1",borderRight: "1px solid #ddd",overflowY: "auto",padding: "10px",minHeight: "300px"}}><Tree showLine defaultExpandAll>{renderTree(treeData)}</Tree></div>{/* 右側表單 */}<divstyle={{flex: "2",padding: "10px",minHeight: "300px"}}>{selectedNode ? (<Form form={form} layout="vertical"><h3>部門信息</h3><Form.Itemlabel="部門名稱"name="name"rules={[{ required: true, message: "請輸入部門名稱" }]}><Input /></Form.Item><Form.Item label="部門編號"><Input value={selectedNode.id} disabled /></Form.Item><div style={{ marginTop: "10px" }}><Buttontype="primary"onClick={handleSaveForm}style={{ marginRight: "10px" }}>保存</Button><Button onClick={() => form.resetFields()}>取消</Button></div></Form>) : (<p>請選擇左側樹節點以查看或編輯部門信息。</p>)}</div>{/* 添加子部門 Modal */}<Modaltitle="添加子部門"visible={addChildModalVisible}onOk={handleAddChild}onCancel={() => setAddChildModalVisible(false)}><Inputplaceholder="請輸入部門名稱"value={newDepartmentName}onChange={(e) => setNewDepartmentName(e.target.value)}/></Modal>{/* 右鍵菜單 */}{contextMenuPosition && (<divstyle={{position: "absolute",top: contextMenuPosition.y,left: contextMenuPosition.x,backgroundColor: "#fff",boxShadow: "0 2px 8px rgba(0,0,0,0.15)",borderRadius: "4px",zIndex: 1000}}onMouseLeave={() => setContextMenuPosition(null)}><divonClick={() => setAddChildModalVisible(true)}style={{padding: "8px 16px",cursor: "pointer",borderBottom: "1px solid #f0f0f0"}}>添加子部門</div></div>)}{/* 插槽 */}<div>{contentSlot1}</div></div>);
}

我們追加了一個代碼,主要是要異步調用后端API的

  // 初始化獲取部門數據React.useEffect(() => {async function fetchDepartments() {try {const result = await $w.cloud.callDataSource({dataSourceName: "departmentManagement_adpurdw",methodName: "getAllDepartments",params: {}});if (result && result.data) {setTreeData(result.data);} else {Modal.warning({ title: "數據加載失敗", content: "未獲取到部門數據。" });}} catch (error) {console.error("Error fetching departments:", error);Modal.error({ title: "加載失敗", content: "獲取部門數據時出錯,請稍后重試。" });}}fetchDepartments();}, [$w]);

這里的dataSourceName和methodName是從我們的API里獲取的
在這里插入圖片描述
部門管理旁邊的相當于我們的dataSourceName,而標識相當于我們的methodName

2 為什么不直接給變量賦值

我一開始認為,我直接獲取數據就可以,比如這樣

const treeData = $w.cloud.callDataSource({dataSourceName: "departmentManagement_adpurdw",methodName: "getAllDepartments",params: {}
});

但這種操作發現樹是空的,并沒有從后臺讀取數據過來。主要的原因是兩方面,首先callDataSource是異步的,你這個執行完了數據其實是沒返回的

兩一方面,數據加載完畢并不會通知React重新渲染組件。改成useEffect的好處是,在組件首次渲染后啟動數據加載任務。當數據加載完成后,通過 setTreeData 更新組件狀態,React 會自動重新渲染組件并展示新數據。

尤其如果部門比較多的情況下,界面可以先出來,等數據獲取完畢組裝好了再次渲染樹形組件,這種體驗就比較好了

3 保存部門信息

數據我們現在已經可以從變量中讀取了,剩下就是添加的時候將新增的部門信息保存到數據源里。這里我們調用微搭的寫入方法,修改如下代碼

// 添加子部門邏輯const handleAddChild = () => {if (!newDepartmentName.trim()) {return Modal.warning({title: "部門名稱不能為空",content: "請輸入部門名稱后重試。",});}// 調用數據源寫入新部門$w.cloud.callDataSource({dataSourceName: "bmb", // 數據源名稱methodName: "wedaCreateV2", // 假設存在 createDepartment 方法params: {data: {bmmc: newDepartmentName, // 部門名稱fbm: { _id: contextMenuTargetId }, // 父部門ID},},}).then((response) => {const newId = response?.id; // 從響應中獲取新節點的 IDif (!newId) {throw new Error("數據源未返回有效ID");}const newChild = {id: newId, // 使用后端返回的 IDname: newDepartmentName,parentId: contextMenuTargetId,children: [],isOpen: false,};// 更新前端樹數據setTreeData((prevTreeData) =>updateTree(prevTreeData, (node) => {if (node.id === contextMenuTargetId) {node.children = [...(node.children || []), newChild];return true;}return false;}));// 關閉模態框并清空輸入setAddChildModalVisible(false);setNewDepartmentName("");Modal.success({title: "添加成功",content: `子部門 "${newDepartmentName}" 已成功添加。`,});}).catch((error) => {console.error("數據源寫入失敗", error);Modal.error({title: "操作失敗",content: "添加子部門時出現錯誤,請稍后重試。",});});};

需要把上邊給的完整代碼的handleAddChild 進行替換,這里主要是調用了微搭的創建單條的API。在創建的時候需要傳遞對應的數據,因為我們的父部門是關聯關系,新版的關聯關系是對象類型,所以我們是按照對象的結構組織了數據。

4 最終的效果

現在已經可以從數據庫里讀取部門的信息,并且按照樹形的結構進行展示
在這里插入圖片描述
點擊右鍵的時候可以添加部門,數據庫里可以看到寫入的數據
在這里插入圖片描述

5 總結

我們本篇介紹了如何將前后端的功能連接起來,從代碼上來講還是比較復雜的,主要需要考慮react組件加載的機制,副作用的理解,以及微搭的異步加載機制。要想理解好這些概念需要你親自做一遍,才會有深入的體會。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/63066.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/63066.shtml
英文地址,請注明出處:http://en.pswp.cn/web/63066.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

spark-sql 備忘錄

wordcount sc.textFile("../data/data.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(__).collect 讀取json 文件 并通過sql 執行 join 查詢 public static void main(String[] args) {SparkSession session SparkSession.builder().master(&qu…

Java并發編程學習(二)

線程的狀態 有說5種的&#xff0c;有說6種的 5種的&#xff0c;從操作系統層面來講 初始狀態&#xff1a;也就是語言層面創建了線程對象&#xff0c;還未與操作系統線程關聯。Java中也就是new了一個線程&#xff0c;還未調用。可運行狀態&#xff1a;&#xff08;就緒狀態&a…

Docker方式安裝人人影視離線完整安裝包

本文軟件由網友 ルリデ 推薦&#xff1b; 上周&#xff0c;人人影視創始人宣布將人人影視二十年字幕數據開源分享 目前提供了兩種使用方式&#xff1a; “在線應用” &#xff1a;意味著需要有互聯網才可以使用。官方提供了網站&#xff1a;https://yyets.click “離線使用” …

Leetcode 3389. Minimum Operations to Make Character Frequencies Equal

Leetcode 3389. Minimum Operations to Make Character Frequencies Equal 1. 解題思路2. 代碼實現 題目鏈接&#xff1a;3389. Minimum Operations to Make Character Frequencies Equal 1. 解題思路 這一題從答題從test的結果來說來說做出的人很少&#xff0c;主要確實有些…

大文件處理的終極武器:Yield詳解

【大文件處理的終極武器&#xff1a;Yield詳解】&#x1f680; 一、大文件處理的痛點 內存限制數據量巨大傳統方法效率低 二、Yield解決方案 def read_large_file(file_path):with open(file_path, r) as file:# 每次只讀取一行&#xff0c;而不是全文for line in file:yie…

SpringBoot 學習

SpringBoot 學習 什么是 Springboot Spring Boot 是 Spring 提供的一個子項目&#xff0c;用于快速構建 Spring 應用程序 傳統的問題&#xff1a; 導入依賴繁瑣項目配置繁瑣 SpringBoot 的特性 起步依賴&#xff1a;整合所有 web 的依賴配置好了自動配置&#xff1a;bean…

到達率的變化動態調整服務器的服務率,實現負載均衡,提高資源利用效率

中心可以根據任務到達率的變化動態調整服務器的服務率,實現負載均衡,提高資源利用效率 服務率和到達率 中心可以根據任務到達率的變化動態調整服務器的服務率,實現負載均衡,提高資源利用效率服務率(Service Rate)到達率(Arrival Rate)控制參數實現負載均衡的方法在云計…

最新全開源IM即時通訊系統源碼(PC+WEB+IOS+Android)部署指南

全開源IM&#xff08;即時通訊&#xff09;系統源碼部署是一個復雜但系統的過程&#xff0c;涉及多個組件和步驟。以下是一個詳細的部署指南&#xff0c;旨在幫助開發者或系統管理員成功部署一個全開源的IM系統&#xff0c;如OpenIM。      IM即時通訊系統源碼準備工作   …

CAD c# 生成略縮圖預覽

代碼如下&#xff1a; using (Transaction tr currentdb.TransactionManager.StartTransaction()){//當前數據庫開啟事務using (Database tempdb new Database(false, true)) //創建臨時數據庫(兩個參數&#xff1a;是否創建符號表&#xff0c;不與當前文檔關聯){try{Bitmap …

CloudberryDB(二) 演化路線圖

CloudberryDB 制定了演化路線圖&#xff08;https://github.com/orgs/cloudberrydb/discussions/369&#xff09;并在逐步改進&#xff0c;這是 Cloudberry Database 發揮獨特價值之處。 計劃、正在進行或已完成的一些工作。 支持輕松升級 PostgreSQL 內核版本。 原有 Greenp…

單片機:實現呼吸燈(附帶源碼)

單片機實現呼吸燈詳細解讀 呼吸燈是一種常見的燈光效果&#xff0c;廣泛應用于電子產品、汽車、家居照明等領域。其基本特性是通過逐漸增亮和減弱的方式&#xff0c;使得燈光呈現出“呼吸”的效果&#xff0c;給人一種平緩、舒適的視覺感受。在嵌入式系統中&#xff0c;呼吸燈…

[面試題]--索引用了什么數據結構?有什么特點?

答&#xff1a;使用了B樹&#xff1a; 時間復雜度&#xff1a;O(logN),可以有效控制樹高 B樹特點&#xff1a; 1.葉子節點之間有相互鏈接的作用&#xff0c;會指向下一個相近的兄弟節點。 MySQL在組織葉子節點使用的是雙向鏈表 2.非葉子節點的值都保存在葉子節點當中 MySQL非葉…

ansible自動化運維(五)roles角色管理

Roles角色管理 角色&#xff08;roles&#xff09;是ansible自1.2版本開始引入的新特性&#xff0c;用于層次性&#xff0c;結構化地組織playbook。 roles能夠根據層次型結構自動裝載變量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。簡單的…

操作系統:文件系統

目錄 1、文件 概念&#xff1a; UNIX文件分類&#xff1a; 2、文件系統 3、文件的訪問方式 順序訪問 隨機訪問 4、文件的組織 邏輯組織 物理組織 5、倒排結構&#xff08;了解&#xff09; 5、文件目錄 文件控制塊&#xff08;FCB&#xff09; ?編輯 目錄項 單…

單元測試-FATAL ERROR in native method: processing of -javaagent failed

文章目錄 前言單元測試-FATAL ERROR in native method: processing of -javaagent failed1. 報錯信息2. 解決方案 前言 如果您覺得有用的話&#xff0c;記得給博主點個贊&#xff0c;評論&#xff0c;收藏一鍵三連啊&#xff0c;寫作不易啊^ _ ^。 ??而且聽說點贊的人每天的運…

決策曲線分析(DCA)中平均凈收益用于評價模型算法(R自定義函數)

決策曲線分析&#xff08;DCA&#xff09;中平均凈收益用于評價模型算法 DCA分析雖然不強調用來評價模型算法或者變量組合的優劣&#xff0c;但是實際應用過程中感覺DCA曲線的走勢和模型的效能具有良好的一致性&#xff0c;其實這種一致性也可以找到內在的聯系&#xff0c;比如…

快速且靠譜的簡單安裝 PostgreSQL 15 yum 安裝postgis3.3

快速且靠譜的簡單安裝 PostgreSQL 15 yum 安裝postgis3.3 1、確保已經安裝了PostgreSQL數據庫。2、添加PostGIS的EPEL倉庫3、使用YUM安裝PostGIS4、以下為其他安裝方式&#xff0c;一個個去找源碼的編譯安裝&#xff0c;過程較為繁瑣&#xff08;不熟路的不推薦&#xff09; 要…

工業大數據分析算法實戰-day05

文章目錄 day05分而治之中的MARS算法神經網絡逼近能力解釋 day05 今天是第5天&#xff0c;昨日從統計分析開始利用統計學的知識判斷當前樣本的分布以及估計總體的參數和假設檢驗的情況&#xff0c;以及介紹了線性回歸算法的相關優化點&#xff0c;但是畢竟線性回歸是線性劃分的…

在Ubuntu服務器上備份文件到自己的百度網盤

文章目錄 概述安裝bypy同步文件定時任務腳本 概述 之前自購了一臺阿里云服務器&#xff0c;系統鏡像為Ubuntu 22.04&#xff0c; 并且搭建了LNMP開發環境&#xff08;可以參考&#xff1a;《Ubuntu搭建PHP開發環境操作步驟(保姆級教程)》&#xff09;。由于項目運行中會產生附…

safe area helper插件

概述 顯示不同機型的必能顯示的區域 實現步驟 引入safearea&#xff0c;引入其中的safearea的csharp 為cancas加入gameobject gameobject中加入safearea腳本 將UI作為這個gameobject的子物體&#xff0c;就可以完成顯示