在早期的隨筆就介紹過,把常規頁面的內容拆分為幾個不同的組件,如普通的頁面,包括列表查詢、詳細資料查看、新增資料、編輯資料、導入資料等頁面場景,這些內容相對比較獨立,而有一定的代碼量,本篇隨筆介紹基於Vue3+Typescript+Setup語法方式,來拆分頁面模塊內容為組件,實現分而治之的處理。 ...
在早期的隨筆就介紹過,把常規頁面的內容拆分為幾個不同的組件,如普通的頁面,包括列表查詢、詳細資料查看、新增資料、編輯資料、導入資料等頁面場景,這些內容相對比較獨立,而有一定的代碼量,本篇隨筆介紹基於Vue3+Typescript+Setup語法方式,來拆分頁面模塊內容為組件,實現分而治之的處理。
1、頁面模塊組件的劃分
我們先來瞭解下常規頁面的內容的整體界面佈局,它包含常規的列表界面,新增、編輯、查看、導入等界面,除了列表頁面,其他內容以彈出層對話框的方式進行處理,如下界面示意圖所示。
這些頁面也可以放在一個大頁面裡面進行處理,邏輯代碼也可以整合一起進行管理,大致的頁面佈局如下所示。
我們看到,如果這樣放置頁面的模塊內容,如果界面控制項比較多的話,頁面代碼會急劇增加,而且由於代碼太多,管理起來也非常不方便,最好的方式,還是拆分進行組件化的管理比較好 。
我們以一個測試用戶的頁面為例來介紹,測試用戶列表界面如下所示。
其中也包括了查看、編輯、新增、導入等界面,我們後面逐一介紹。
2、頁面組件的開發
我們前面介紹到,整個頁麵包含了列表界面,新增、編輯、查看、導入等界面,除了列表頁面,其他內容以彈出層對話框的方式進行處理。
我們分別創建index.vue代表主列表頁面內容,view代表查看頁面、edit代表新增或者編輯頁面(兩個頁面類似,因此整合一起更精簡),import代表導入頁面,一起放在一個testuser頁面目錄中,作為一個模塊頁面。
我們先以view.vue查看頁面為例進行介紹,它是一個查看明細的界面,因此也是一個彈出對話框頁面,我們把它的代碼處理如下所示。
<template> <el-dialog title="查看信息" v-model="isVisible" v-if="isVisible" append-to-body @close="closeDialog(viewRef)"> <el-form ref="viewRef" :model="viewForm" label-width="80px"> <el-tabs type="border-card"> <el-tab-pane label="基本信息"> <el-row> <el-col :span="12"> <el-form-item label="姓名"> <el-input v-model="viewForm.name" disabled /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="性別"> <el-input v-model="viewForm.sex" disabled /> </el-form-item> </el-col> .................//省略代碼 </el-tab-pane> </el-tabs> </el-form> <template #footer> <span class="dialog-footer"> <el-button @click="closeDialog(viewRef)">關閉</el-button> </span> </template> </el-dialog> </template>
其他的js代碼採用tyepscript語法,我們把它放在
<script setup lang="ts"> //邏輯代碼 </script>
為了把組件的方法公開,我們先定義一個介面類型,便於引用的時候,代碼進行約束提示。
<script setup lang="ts"> //組件的介面類型 export interface ExposeViewType { show(id?: string | number): Function; } ............ //顯示視窗 const show = (id: string | number) => { //處理代碼 }; //暴露組件屬性和方法 defineExpose({ show }); </script>
這樣我們在父頁面中使用子模塊組件的時候,就可以通過公開的方法進行調用了。
//父頁面index.vue <!--查看詳細組件界面--> <view-data ref="viewRef" /> <!--新增、編輯組件界面--> <edit-data ref="editRef" @submit="saveEdit" /> <!--模板導入信息--> <import-data ref="importRef" @finish="finishImport" /> </div> </template> <script setup lang="ts"> ........ import ViewData, { ExposeViewType } from "./view.vue"; import EditData from "./edit.vue"; import ImportData from "./import.vue"; ...... // 顯示查看對話框處理 const viewRef = ref<ExposeViewType | null>(); //查看表單引用 //const viewRef = ref<InstanceType<typeof ViewData>>(); function showView(id) { if (isEmpty(id)) { warnMessage("請選擇編輯的記錄!"); return; } viewRef.value.show(id); }
我們通過const viewRef = ref<ExposeViewType | null>(); 就可以獲得組件類型的引用,然後調用組件的介面方法即可。
viewRef.value.show(id);
在查看頁面的組件定義模板中,我們大致代碼如下所示。
聲明瞭對應的引用,以及表單對象,以及提供相應的方法進行處理,這些內容對父頁面封裝了細節。
<script setup lang="ts"> //組件的介面類型 export interface ExposeViewType { show(id?: string | number): Function; } import { reactive, ref, onMounted, watch, computed, nextTick } from "vue"; import { FormInstance} from "element-plus"; defineOptions({ name: "ViewData" }); //定義組件名稱 //聲明Props的介面類型 interface Props { visible?: boolean; // 是否顯示 id?: string | number; // 接受外部v-model傳入的id值 } //使用預設值定義Props const props = withDefaults(defineProps<Props>(), { visible: false, value: null }); //聲明組件事件 interface Emits { (e: "update:id", id: string | number): void; (e: "update:visible", visible: boolean): void; (e: "close"): void; //(e: "submit"): void; } //定義組件事件 const emit = defineEmits<Emits>();
我們定義了組件名稱、組件的Props屬性、以及Emit事件,Emit事件如果想簡單化一點,也可以直接使用名稱即可。
例如,有時候我們會直接聲明名稱進行定義Emit,如下所示。
//定義觸發事件 const emit = defineEmits(["error", "success", "remove", "change"]);
顯示頁面的方法,是公開給父頁面進行調用的,因此接收一個id參數,並根據id值,利用axios訪問遠端API介面獲取數據,進行賦值顯示即可。
//顯示視窗 const show = (id: string | number) => { if (!isNullOrUnDef(id)) { testuser.Get(id).then(data => { // console.log(data); Object.assign(viewForm, data); isVisible.value = true; //顯示對話框 }); } };
關於axios訪問遠端API介面的類實現,可以參考隨筆《基於SqlSugar的開發框架循序漸進介紹(10)-- 利用axios組件的封裝,實現對後端API數據的訪問和基類的統一封裝處理》進行瞭解。
這裡的TestUser的APi類,繼承自基類BaseApi,因此擁有常規的處理方法。
最後,查看明細的視窗關閉後,需要設置一下視窗的相關標記。
let isVisible = ref(false); //是否顯示查看對話框 function closeDialog(formEl: FormInstance | undefined) { // 關閉常規 添加、編輯、查看、導入等視窗處理 isVisible.value = false; if (!formEl) { formEl.resetFields(); } emit("close"); //關閉 }
由於視窗內部的顯示標記和Prop屬性的關係,我們需要處理一下,對他們進行Watch監控,並處理值的變化。
//監控某些值的變化,進行處理 watch( () => props.visible, newValue => { isVisible.value = newValue; emit("update:visible", newValue); } ); watch( () => isVisible, newValue => { // console.log(newValue); emit("update:visible", newValue.value); } );
表單的form對象,我們根據後端數據結構進行生成即可。
const viewRef = ref<FormInstance>(); //表單引用 // 表單屬性定義 let viewForm = reactive({ id: "", name: "", sex: "", birthDate: "", nationality: "", education: "", marriage: "", star: "", height: "", weight: "", ................. createTime: "", extensionData: "" // 擴展數據 });
有了這些處理,我們查看詳細的頁面彈出和關閉就正常了。頁面效果如下所示。
新建、編輯頁面也是類似,只是在保存數據後觸發相關的事件,讓父頁面進行更新顯示即可。
<!--查看詳細組件界面--> <view-data ref="viewRef" /> <!--新增、編輯組件界面--> <edit-data ref="editRef" @submit="saveEdit" /> <!--模板導入信息--> <import-data ref="importRef" @finish="finishImport" />
如編輯、新增頁面的父組件頁面,也是只需關註他的打開和完成處理即可。
//新增、編輯表單引用 const editRef = ref<ExposeViewType | null>(); //顯示新增對話框 function showAdd() { editRef.value.show(); } // 顯示編輯對話框 function showEdit(id) { if (isEmpty(id)) { warnMessage("請選擇編輯的記錄!"); return; } editRef.value.show(id); } //新增/更新後刷新 function saveEdit() { getlist(); }
而在編輯信息的組件頁面內部,就需要判斷是更新還是插入記錄的處理,完成後再拋出事件即可。
// 保存數據處理 async function submitData() { var formEl = editRef.value; if (!formEl) return; // console.log(editForm); await formEl.validate(async valid => { if (valid) { //驗證成功,執行下麵方法 var result = false; if (isAdd.value) { result = await testuser.Create(editForm); //新增保存 } else { result = await testuser.Update(editForm); //編輯保存 } if (result) { successMessage("操作成功!"); // 提示信息 emit("submit"); // 提示刷新數據 closeDialog(formEl); // 重置視窗狀態 } else { errorMessage("操作失敗"); } } })
導入數據頁面,大體也是類似,不過由於涉及到更多的是對導入處理的規則處理,需要封裝一下相關的組件功能,因此後面再獨立介紹細節實現。
系列文章:
《基於SqlSugar的開發框架的循序漸進介紹(1)--框架基礎類的設計和使用》
《基於SqlSugar的開發框架循序漸進介紹(2)-- 基於中間表的查詢處理》
《基於SqlSugar的開發框架循序漸進介紹(3)-- 實現代碼生成工具Database2Sharp的整合開發》
《基於SqlSugar的開發框架循序漸進介紹(4)-- 在數據訪問基類中對GUID主鍵進行自動賦值處理 》
《基於SqlSugar的開發框架循序漸進介紹(5)-- 在服務層使用介面註入方式實現IOC控制反轉》
《基於SqlSugar的開發框架循序漸進介紹(6)-- 在基類介面中註入用戶身份信息介面 》
《基於SqlSugar的開發框架循序漸進介紹(7)-- 在文件上傳模塊中採用選項模式【Options】處理常規上傳和FTP文件上傳》
《基於SqlSugar的開發框架循序漸進介紹(8)-- 在基類函數封裝實現用戶操作日誌記錄》
《基於SqlSugar的開發框架循序漸進介紹(9)-- 結合Winform控制項實現欄位的許可權控制》
《基於SqlSugar的開發框架循序漸進介紹(10)-- 利用axios組件的封裝,實現對後端API數據的訪問和基類的統一封裝處理》
《基於SqlSugar的開發框架循序漸進介紹(11)-- 使用TypeScript和Vue3的Setup語法糖編寫頁面和組件的總結》
專註於代碼生成工具、.Net/.NetCore 框架架構及軟體開發,以及各種Vue.js的前端技術應用。著有Winform開發框架/混合式開發框架、微信開發框架、Bootstrap開發框架、ABP開發框架、SqlSugar開發框架等框架產品。轉載請註明出處:撰寫人:伍華聰 http://www.iqidi.com