WTM框架使用技巧之:Layui版本嫁接Vue+ElementUI
快點關注我們吧
作者介紹
莊星睿,現就職于海運物流行業,威海新海豐物流有限公司,IT技術兼管理職務。
從事過winform,wpf技術開發,自2019年接觸wtm框架后,熱衷使用wtm框架開發物流公司內部軟件。
如高度定制化的SOC自備箱管理系統,主要解決日照分公司的新興海鐵聯運業務中集裝箱管理混亂問題,由于wtm特有的結構化編程理念,快捷高效的使用方式,能夠及時有效的滿足業務使用,克服以往需求變更快,代碼更新慢,無法滿足業務發展的弊端,可以說wtm的出現,很好的解決了這些問題。
為什么要這樣做
layui版本具備很多優點:組件齊全、ide提醒程度高、代碼量少、依賴少、編譯快、運行快,非常適合一個人的開發團隊
但它也有很多缺點,比如說組件靈活度低、可控性差。
受blazor ssr的思路啟發,將vue嫁接進layui版本中,在大部分常規頁面中,保留layui的快速高效用法。在極少部分需要大量定制化的頁面,采用vue+elementUI的方式編寫,既能保證開發效率,又能解決復雜頁面編寫。
因此本文拿一個頁面改造的例子,旨在拋磚引玉。
準備工作
在_Layout中引入包
_Layout.cshtml文件位于Views\Shared\_Layout.cshtml
操作步驟
引入element-ui.css
引入vue.js
引入element-ui.js
<!-- 引入樣式 --> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"><!-- 引入組件庫 --> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script src="https://unpkg.com/element-ui/lib/index.js"></script>本篇文章使用的vue版本為2.6.14
如下圖示
改造一個index.cshtml頁面
原頁面代碼為
@model ReaTms.ViewModel.TruckerVMs.TruckerListVM @inject IStringLocalizer<Program> Localizer;<wt:searchpanel vm="@Model" reset-btn="true"><wt:row items-per-row="ItemsPerRowEnum.Three"><wt:textbox field="Searcher.TruckerIdentify" /><wt:textbox field="Searcher.TruckerName" /><wt:textbox field="Searcher.TruckerPhone" /></wt:row> </wt:searchpanel> <wt:grid?vm="@Model"?url="/Trucker/Search"?/>顯示效果為
但我不滿意layui的表格,功能太少了,準備使用element-ui的table來替代。
開始改造:
處理原頁面
干掉<wt:grid/>組件
將<wt:grid vm="@Model" url="/Trucker/Search" />打上注釋,或者干脆直接刪掉。
重寫<wt:searchpanel/>的搜索按鈕點擊事件
我們知道,wtm中<wt:searchpanel/>的搜索按鈕默認id為wtSearchBtn_@Model.UniqueId(如果對這一點不了解同學,請查看源碼src/WalkingTec.Mvvm.TagHelpers.LayUI/Form/SearchPanelTagHelper.cs),那么我們只要拿到這個id,在頁面加載的時候,卸載掉框架默認的點擊事件,重新綁定一個新的點擊事件就可以了。
這里為什么要卸載掉點擊事件呢?因為默認的點擊事件會調用layui.table去加載數據,而我們在第一步中已經將<wt:grid/>組件移除了,如果不卸載掉默認事件的話,點擊按鈕會報錯。
參照以下代碼:
@model ReaTms.ViewModel.TruckerVMs.TruckerListVM @inject IStringLocalizer<Program> Localizer;<wt:searchpanel vm="@Model" reset-btn="true"><wt:row items-per-row="ItemsPerRowEnum.Three"><wt:textbox field="Searcher.TruckerIdentify" /><wt:textbox field="Searcher.TruckerName" /><wt:textbox field="Searcher.TruckerPhone" /></wt:row> </wt:searchpanel> <script>$().ready(() => {$('#wtSearchBtn_@Model.UniqueId').off('click').on('click', e => {e.stopPropagation();//阻止點擊事件繼續冒泡,使pannel不折疊//查詢方法寫在這里,下文會繼續講到});}); </script>定義一個vue的根容器。切記:不要在這個容器中寫任何<script>代碼,否則vue會報警告
<div id="app"> </div>創建vue實例,并創建表格數據對象
注意:在cshtml文件中不能使用vue的事件綁定符號@,請使用全稱v-on:
到這一步后,頁面的樣子是這樣的
@model ReaTms.ViewModel.TruckerVMs.TruckerListVM @inject IStringLocalizer<Program> Localizer;<wt:searchpanel vm="@Model" reset-btn="true"><wt:row items-per-row="ItemsPerRowEnum.Three"><wt:textbox field="Searcher.TruckerIdentify" /><wt:textbox field="Searcher.TruckerName" /><wt:textbox field="Searcher.TruckerPhone" /></wt:row> </wt:searchpanel> <div id="app"></div> <script>$().ready(() => {$('#wtSearchBtn_@Model.UniqueId').off('click').on('click', e => {e.stopPropagation();//阻止點擊事件繼續冒泡,使pannel不折疊//查詢方法寫在這里,下文會繼續講到});});var app = new Vue({el: '#app',data: {TableItems: {} //表格數據對象},methods: {}}); </script>創建element-ui的table
注意這里綁定的是TableItems.Data,這是因為wtm后端傳過來的數據是這種格式的。
給第1步中的搜索按鈕編寫查詢方法。
使用ff.GetFormData(formId)的形式,拿到查詢條件的表單數據。
formId可以根據wtm的約定,使用wtForm_@Model.UniqueId拿到。
使用$.post訪問后臺數據接口,拿到數據后將數據賦值給vue的TableItems對象。
<script>$().ready(() => {$('#wtSearchBtn_@Model.UniqueId').off('click').on('click', e => {e.stopPropagation();//阻止點擊事件繼續冒泡,使pannel不折疊//查詢方法寫在這里,下文會繼續講到let data = ff.GetFormData('wtForm_@Model.UniqueId');//拿到查詢條件的表單數據$.post('/Trucker/Search', data, resp => {app.TableItems = resp;},'json');});});var app = new Vue({el: '#app',data: {TableItems: {} //表格數據對象},methods: {}}); </script>至此,我們的頁面就跑起來了。
添加分頁組件
分別綁定:current-page="TableItems.Page"、:total="TableItems.Count"
再次刷新一下頁面看下效果,分頁組件能夠讀取當前頁面和總條數了,但所有數據都顯示出來了,并沒有真正分頁。
完善分頁組件的功能-分頁顯示
首先創建一個對象,用來對應wtm中的Searcher,這里只需創建Page和Limit字段就行了,表單字段可以使用對象復制功能,復制過來
對第6步的查詢方法進行封裝,封裝的過程中,使用$.extend(newobj,oldobj)的方法,將表單數據組裝成一個分頁查詢對象
此時頁面能夠實現分頁顯示了,但還不能實現跳轉頁面
完善分頁組件的功能-跳轉頁面
上一步完成后,頁面只是實現了分頁,但還不能跳轉 ,我們繼續實現它
創建一個頁面跳轉函數onPagination(newPage)
在el-pagination添加跳轉事件,v-on:current-change="onPagination"、?v-on:size-change="onPagination"
此時,已經實現了頁面分頁,分頁跳轉
頁面的完整代碼為
增加一個Descriptions(描述列表)
想實現效果:點擊表格的行,能夠在下方實現這行數據的明細
創建當前行的綁定對象SelectedRow
配置el-table的highlight-current-row,實現點擊行自動選中
給el-table的current-change事件創建回調函數onCurrentChange(currentRow, oldCurrentRow),
增加一個el-descriptions
此時,頁面效果如下圖
增加工具欄及權限控制
使用Wtm.IsAccessable來控制權限
使用ff.OpenDialog()來打開一個窗口
此時能夠打開窗口創建數據,但創建完成后,數據不能自動刷新。
3. 在控制器中,重寫刷新頁面的js函數AddCustomScript("app.onSearch();");。
至此,頁面能夠自動刷新了,其他工具欄按鈕可參照該方法創建,復雜功能可參照element的官方案例。
本文僅就這問題談些淺顯的看法,意在拋磚引玉,以就教于各界專家。感謝WTM的作者劉亮,免費授權使用如此優秀的框架,造福大家。
https://wtmdoc.walkingtec.cn/
最終代碼
@model ReaTms.ViewModel.TruckerVMs.TruckerListVM @inject IStringLocalizer<Program> Localizer;<wt:searchpanel vm="@Model" reset-btn="true"><wt:row items-per-row="ItemsPerRowEnum.Three"><wt:textbox field="Searcher.TruckerIdentify" /><wt:textbox field="Searcher.TruckerName" /><wt:textbox field="Searcher.TruckerPhone" /></wt:row> </wt:searchpanel> <div id="app"><el-row>@if (Model.Wtm.IsAccessable("/Trucker/Create")) {<el-button type="primary" onclick="ff.OpenDialog('/Trucker/Create',1,'創建',1000)">創建</el-button>}</el-row><el-table :data="TableItems.Data" highlight-current-row v-on:current-change="onCurrentChange"><el-table-column prop="TruckerName" label="司機" /><el-table-column prop="TruckerPhone" label="電話" /><el-table-column prop="TruckerIdentify" label="身份證" /></el-table><el-pagination :current-page="TableItems.Page":total="TableItems.Count":page-size="10"layout="total, sizes, prev, pager, next, jumper"v-on:current-change="onPagination" v-on:size-change="onPagination"></el-pagination><el-descriptions title="司機信息" v-if="SelectedRow!=null"><el-descriptions-item label="司機">{{SelectedRow.TruckerName}}</el-descriptions-item><el-descriptions-item label="手機號">{{SelectedRow.TruckerPhone}}</el-descriptions-item><el-descriptions-item label="身份證">{{SelectedRow.TruckerIdentify}}</el-descriptions-item><el-descriptions-item label="創建人"><el-tag size="small">{{SelectedRow.CreateBy}}</el-tag></el-descriptions-item><el-descriptions-item label="創建時間">{{SelectedRow.CreateTime}}</el-descriptions-item><el-descriptions-item label="備注">{{SelectedRow.Remark}}</el-descriptions-item></el-descriptions> </div> <script>$().ready(() => {$('#wtSearchBtn_@Model.UniqueId').off('click').on('click', e => {e.stopPropagation();//阻止點擊事件繼續冒泡,使pannel不折疊app.onSearch();});});var app = new Vue({el: '#app',data: {SelectedRow: null,TableItems: {}, //表格數據對象TableSearcher: { //對應wtm中的Searcher"Searcher.Page": 1,"Searcher.Limit": 10}},methods: {onSearch() {//將表單數據復制到this.TableSearcher中,組裝成一個完整的查詢對象$.extend(this.TableSearcher, ff.GetFormData('wtForm_@Model.UniqueId'));$.post('/Trucker/Search', this.TableSearcher, resp => {this.TableItems = resp;},'json');},onPagination(newPage) {this.TableSearcher["Searcher.Page"] = newPage;this.onSearch();},onCurrentChange(currentRow, oldCurrentRow) {this.SelectedRow = currentRow;}}}); </script>控制器
#region Create[ActionDescription("Sys.Create")]public ActionResult Create(){var vm = Wtm.CreateVM<TruckerVM>();return PartialView(vm);}[HttpPost][ActionDescription("Sys.Create")]public ActionResult Create(TruckerVM vm){if (!ModelState.IsValid){return PartialView(vm);}else{vm.DoAdd();if (!ModelState.IsValid){vm.DoReInit();return PartialView(vm);}else{return FFResult().CloseDialog().AddCustomScript("app.onSearch();");}}}#endregion總結
以上是生活随笔為你收集整理的WTM框架使用技巧之:Layui版本嫁接Vue+ElementUI的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Net 5.0 快速开发框架 YC.Bo
- 下一篇: Abp Vnext Vue3 的版本实现