今天要作的,就是在上一篇文章的基礎上,進行功能頁面的開發。簡單點說呢,就是與後端的數據交互和怎麼把數據展現出來,用到的資源主要是element-ui和vue-resource,其它參考(vue-resource插件使用)。今天講到的一些功能開發,主要就是請求列表數據,詳情數據,分頁功能操做,搜索,搜索標籤等的開發。今天這個,按照下面步驟,一步一步來。一個一個功能的作!javascript
我以‘回款管理’(cashList.vue
)爲開發的demo,下文講到的各類增刪改查都是在這個文件上操做,你們注意喔!這雖然是作5個功能,其實就只有兩個接口。(按照我開發項目,後端提供的接口說明)html
下面分析下咱們公司後端給我提供的其中兩個接口。並且兩個接口都是get
請求。vue
let http_url={ list:'http://xxx.xxx.com/xxx/cash/list', detail:'http://xxx.xxx.com/xxx/cash/detail' } /** http_url.list接口接受參數 ordId //String,訂單號 cashId //String.回款編號 custoName //String,客戶名稱,模糊查詢 cashType //int,回款類型 cashStatus //int,回款狀態 userName//String,採購人,模糊查詢 userMobile //String,採購人電話,模糊查詢 //上面是搜索查詢的字段,下面是數據的頁碼和每頁的條數 pogeNo //int,頁碼(必填) pageSize //int,每頁顯示條數(必填) http_url.detail接口接受參數(按照我開發項目) cashId //String.回款編號(必填) **/
首先,因爲接口http_url.list接口能夠接受一些搜索,先把整個準備了!java
而後再到頁碼的一些東西,主要是三個,當前頁碼,每頁條數。(本身隨便設的默認值)
數據就變成了webpack
data(){ return { pageSize:10,//每頁條數 allCount:0,//記錄總數 currentPage:1,//當前頁碼 cashList: [], //列表數組(如今是準備請求接口,不須要模擬的數據,因此設置一個空數組) keyFrom: {....}//搜索字段 } }
你們可能不明白,一樣是請求的參數,頁碼這些爲何要和搜索字段分開放?之因此分開放是由於頁碼這些,到下面分頁的時候要單獨使用,並且作搜索的時候,頁碼又不是搜索字段,因此就分開放,下面會詳情的說明!git
準備就準備這麼多了,以後還要用到什麼數據,之後再添加!github
先別急着寫,你們能夠想下,搜索字段那裏,好比我只想根據回款ID(cashId
)查詢呢?
難道這樣發送請求?http://xxx.xxx.com/xxx/cash/l...''&cashId=xxx&custoName=''&cashType=''&cashStatus=''&userName=''&userMobile=''
真不必,咱們想要的是這樣http://xxx.xxx.com/xxx/cash/l...
因此,請求以前,先寫一個方法,就是過濾搜索字段(keyFrom
)裏面,值爲空的屬性。web
/** * 清除對象中值爲空的屬性 */ filterParams(obj){ let _form = obj, _newPar = {}, testStr; //遍歷對象 for (let key in _form) { testStr = null; //若是屬性的值不爲空。 //注意,不要這樣判斷if (_form[key])。由於有些屬性的值可能爲0,到時候就會被過濾掉 if (_form[key] !== null && _form[key] !== "") { //把值添加進新對象裏面 _newPar[key]=_form[key].toString() } } //返回對象 return _newPar; }
getList(){ //過濾搜索字段值爲空的屬性,而後對象合併,合併上頁碼。 let _par = Object.assign(this.filterParams(this.keyFrom), { pageNo: this.currentPage, pageSize: this.pageSize }); this.$http.get(http_url.list, { params: _par }).then(function (res) { }); }
mounted(){ this.getList(); },
爲了能更直觀看到結果,我在瀏覽器直接打開這個接口vue-router
須要的有的字段都有了
那麼接下來就接收返回的字段數據庫
getList(){ //過濾搜索字段值爲空的屬性,而後對象合併,合併上頁碼。 let _par = Object.assign(this.filterParams(this.keyFrom), { pageNo: this.currentPage, pageSize: this.pageSize }); this.$http.get(http_url.list, { params: _par }).then(function (res) { res=res.body; //若是請求成功了,這接口code爲0表明請求成功。具體怎樣判斷還須要看接口 if(res.code===0){ //設置列表數據 this.cashList = res.datas.entityList; } else{ this.$message.error(res.msg); } }); }
怎麼鋪,隨機應變唄!
來到el-table
這個標籤這裏。不知道排版佈局的話,參考上一篇文章喔!不要不知道我在說什麼!
而後開始寫<el-table-column></el-table-column>
下面簡單寫幾個栗子
點擊回款id,會出來詳情頁面(詳情頁面的方法getDetail
咱們到下面寫,如今)
<el-table-column label="編號" width="180"> <template scope="scope"> <a href="javascript:;">{{scope.row.cashId}}</a> </template> </el-table-column>
訂單id只須要顯示,就簡單了
<el-table-column label="訂單編號" width="160"> <template scope="scope"> <span>{{ scope.row.ordId }}</span> </template> </el-table-column>
回款時間須要把時間戳轉成yyyy-mm-dd hh:mm:ss
<el-table-column label="回款時間" min-width="180"> <template scope="scope"> <span>{{new Date(scope.row.cashDate).toLocaleDateString().replace(/\//g, '-')}} {{new Date(scope.row.cashDate).toTimeString().split(' ')[0]}}</span> </div> </template> </el-table-column>
回款狀態須要把狀態碼轉換成文字
<el-table-column> <template scope="scope"> <span v-if="scope.row.cashStatus === 0">待回款</span> <span v-if="scope.row.cashStatus === 1">部分回款</span> <span v-if="scope.row.cashStatus === 2" style="color: green">已回款</span> <span v-if="scope.row.cashStatus === 3" style="color: red">已取消</span> </template> </el-table-column>
金額在數據庫以分爲單位,如今須要轉換成元
<el-table-column label="回款金額(元)" width="150"> <template scope="scope"> <span>{{ (scope.row.cashAmount / 100).toFixed(2) }}</span> </template> </el-table-column>
好了,典型的幾種數據,以及處理的方法,就是在這裏了。固然這個只是作展現做用,怎麼展現是看項目的需求的!
小夥伴們運行起來的時候,可能會發現兩個問題。
1.好比網速比較慢的時候,請求沒完成的時候,就會看到這個(這個提醒是element-ui提供的,只要發現cashList是空的,就會出現這個提醒)
若是咱們想體驗好一點,作一個提示加載中的提示呢
這個簡單的。首先在el-table上,設置v-loading="loading"。
而後在data設置loading這個屬性
而後就是在請求那裏
進入方法的時候,設置loading=true,請求完了再設置成false。(當loading=true時,加載中的提示就會出現。
getList(){ //顯示加載中提示 this.loading=true; //過濾搜索字段值爲空的屬性,而後對象合併,合併上頁碼。 let _par = Object.assign(this.filterParams(this.keyFrom), { pageNo: this.currentPage, pageSize: this.pageSize }); this.$http.get(http_url.list, { params: _par }).then(function (res) { res=res.body; //若是請求成功了,這接口code爲0表明請求成功。具體怎樣判斷還須要看接口 if(res.code===0){ //設置列表數據 this.cashList = res.datas.entityList; //關閉加載中提示 this.loading=false; } else{ this.$message.error(res.msg); } }); }
2.再有就是,若是展現的數據,有些是空的字符串,或者是null的話,在列表上就會看到。
這樣提示不太友好,由於只顯示空白一片,用的人可能不知道怎麼回事。這時候加個判斷,若是某一個屬性的值,爲空字符串或者null,就替換成‘--’。
getList(){
//顯示加載中提示 this.loading=true; //過濾搜索字段值爲空的屬性,而後對象合併,合併上頁碼。 let _par = Object.assign(this.filterParams(this.keyFrom), { pageNo: this.currentPage, pageSize: this.pageSize }); this.$http.get(http_url.list, { params: _par }).then(function (res) { res=res.body; //若是請求成功了,這接口code爲0表明請求成功。具體怎樣判斷還須要看接口 if(res.code===0){ //設置列表數據 this.cashList = res.datas.entityList; this.cashList.map(function (value) { for (let key in value) { //不要if(value[key])判斷,有的值多是0,會把0過濾 if (value[key] === null || value[key] === '') { value[key] = '--' } } }); //關閉加載中提示 this.loading=false; } else{ this.$message.error(res.msg); } }); }
而後咱們就會看到這樣的結果,就明確的說明了,這裏的值爲空
詳情的數據,就是點擊列表的任何一條數據,出來一個詳情頁面。
先在瀏覽器請求一下(看下有身什麼字段,能夠方便在html裏面鋪數據),看到有不少字段。
如今項目上,用的是這個效果,咱們如今也用這個吧!
代碼以下,castInfo是在data聲明的的變量,做用是儲存請求回來的字段,包含字段如上圖!
<!-- 詳情彈窗 --> <div class="cash-content-box" v-if="contentShow" :class="{'show-box':contentClass}"> <div class="cash-main"> <p class="content-close"><a href="javascript:;" @click="hideContentDo">X</a></p> <div class="content-top"> <h2>回款金額:{{(castInfo.cashAmount / 100).toFixed(2)}}元</h2> <p> 回款編號:{{castInfo.cashId}}<span>|</span>回款日期:{{new Date(castInfo.cashDate).toLocaleDateString().replace(/\//g, '-') }}</p> </div> <div class="content-type"> <ul class="flli"> <li v-if="castInfo.cashStatus===0">回款狀態:待回款</li> <li v-else-if="castInfo.cashStatus===1">回款狀態:部分回款</li> <li v-else-if="castInfo.cashStatus===3">回款狀態:已取消</li> <li v-else>回款狀態:已回款</li> </ul> <div class="clear"></div> </div> <div class="content-tab"> <ul class="flli"> <li class="cur">概要</li> </ul> <div class="clear"></div> </div> <div class="content-info"> <h3 class="content-title">基本信息</h3> <table class="content-table"> <tr> <td>回款編號</td> <td><span>{{castInfo.cashId}}</span></td> </tr> <tr> <td>回款金額</td> <td>{{(castInfo.cashAmount / 100).toFixed(2)}}元</td> </tr> <tr> <td>帳戶類型</td> <td v-if="castInfo.cashAccountType"> {{castInfo.cashAccountType===1?'公帳':'其餘帳戶'}} </td> <td v-else-if="castInfo.cashAccountType===0">其餘帳戶</td> <td v-else>--</td> </tr> <tr> <td>回款類型</td> <td v-if="castInfo.cashType===0">當即回款</td> <td v-if="castInfo.cashType===1">按期回款</td> <td v-if="castInfo.cashType === '--'">--</td> </tr> <tr> <td>回款日期</td> <td>{{new Date(castInfo.cashDate).toLocaleDateString().replace(/\//g, '-') }}</td> </tr> <tr> <td>回款狀態</td> <td v-if="castInfo.cashStatus===0">待回款</td> <td v-if="castInfo.cashStatus===1">部分回款</td> <td v-if="castInfo.cashStatus===2">已回款</td> <td v-if="castInfo.cashStatus===3">已取消</td> <td v-if="castInfo.cashStatus === '--'">--</td> </tr> <tr> <td>回款渠道</td> <td v-if="castInfo.payChannel === 'zfb'">支付寶</td> <td v-if="castInfo.payChannel === 'wx_pay'">微信支付</td> <td v-if="castInfo.payChannel === 'bank_trans'">銀行轉帳</td> <td v-if="castInfo.payChannel === 'easy_pay'">蘇寧易付寶</td> <td v-if="castInfo.payChannel === 'yi_ji_fu'">易極付</td> <td v-if="castInfo.payChannel === 'ljl_pay'">藍金靈支付</td> <td v-if="castInfo.payChannel === '--'">--</td> </tr> <tr> <td>備註</td> <td>{{castInfo.remark}}</td> </tr> </table> </div> </div> </div> <!--遮罩層--> <div class="cash-content" v-show="contentShow" @click="hideContentDo"></div>
遮罩層和詳情div裏面的樣式我不說了。最外層的樣式是下面這樣
{ width: 700px; z-index: 1006; position: fixed; top: 0; right: 0; transform: translate3d(700px, 0, 0); height: 100%; background: #535968; transition: transform 1s; }
transform: translate3d(700px, 0, 0);
是爲了一開始吧它隱藏起來,相信你們都看得懂!怎麼讓它顯示出來呢,把樣式改爲transform: translate3d(0, 0, 0);
這個就好了,動畫效果自動會有,由於加了transition: transform 1s;
。
getDetali: function (id) { //contentShow控制詳情頁和遮罩層的顯示,contentClass控制詳情頁的動畫,castInfo爲記錄請求回來的數據。你們要在data上面聲明哦! //也是一樣的處理方式,區別就是this.$loading是element提供的全局組件,效果就是整個屏幕顯示加載中。 let loadingContent = this.$loading({ text: '正在加載中...' }); //顯示詳情 this.$http.get(http_url.detail, { params: { cashId: id } }).then(function (res) { res = res.body; if (res.code === 0) { this.castInfo = res.datas.castInfo; //關閉加載中提示 loadingContent.close(); //顯示詳情的div this.contentShow = true; //爲了確保看到動畫效果,因此讓遮罩層和詳情的DIV先顯示,再執行this.contentClass = true;讓詳情DIV從右至左的出現 setTimeout(() => { this.contentClass = true; }) } else { this.$message.error(res.msg); } }); }
既然是詳情,又出現,就有隱藏
/** * @description 隱藏詳情 */ hideContentDo(){ //先執行this.contentClass = false。讓詳情DIV從左至右回去,等回去了以後,再執行this.contentShow = false;在隱藏div,不然會看不到動畫效果。設置的時間,就是當時動畫的時間!transition: transform 1s this.contentClass = false; setTimeout(() => { this.contentShow = false; }, 1000) },
分頁這個功能,你們可能都接觸過,寫得也是很複雜。可是今天用了element-ui提供的分頁組件,就簡單多了!
在.cash-table
這個DIV下面,直接引入下面的代碼
<div class="cash-page"> <el-pagination @current-change="handleCurrentChange" :page-size="pageSize" :current-page="currentPage" layout="total, prev, pager, next, jumper" :total="allCount"> </el-pagination> </div>
handleCurrentChange這個方法待會寫,allCount,pageSize,currentPage這三個變量,都是以前已經聲明瞭的,你們往上翻下就知道了!參數你們看官網-分頁
/** * @description 分頁處理 * @param val */ handleCurrentChange(val) { //val是組件的返回值,返回當前是第幾頁 //而後把值賦值給currentPage。 this.currentPage = val; //而後再次調用getList。更新cashList this.getList(); }
這個的代碼看着很簡單。你們可能會不太理解原理。下面我簡單分析下。
1.首先執行this.currentPage = val;
獲取當前是第幾頁,好比我點擊第二頁。this.currentPage
的值就是2。
2.而後執行this.getList();
。這個時候,在方法裏面。
至關於發送了這個請求http://xxx.xxx.com/xxx/cash/l...
而後在執行下去,cashList這個數組就更新了。咱們分頁就開發完了。
搜索功能這個太常見了,我如今作的項目,搜索需求就是。
而後輸入再點擊
交互很容易理解。就是輸入,而後再輸出結果,如上圖,我在回款ID下面的文本框輸入‘M2017070400060002’。而後點擊搜索。就會出現輸出結果。
下面,咱們一步步來
filterSearch
這個方法,代碼以下/** * 顯示與隱藏搜索 */ filterSearch(){ //filterModel小夥伴們要在data上聲明哦,初始值爲false。這個值是記錄當前是否是要顯示搜索框,進行搜索的。 //當前是否須要搜索狀態 if (this.filterModel) { this.cashList.splice(0, 1); } else { this.cashList.unshift({ "cashId": "#", }) } //顯示或隱藏搜索 this.filterModel = !this.filterModel; }
首先,清楚一個。後端返回的數據(如上圖),並非全部的字段都是能夠進行搜索的字段。只有這幾個字段(以下圖),才能夠進行搜索。
因此,這裏我分三種請況。
一種狀況是,好比回款編號,能夠進行搜索的字段。
//修改前 <el-table-column label="回款編號" width="200"> <template scope="scope"> <span>{{ scope.row.cashId }}</span> </template> </el-table-column>
//修改後 <el-table-column label="回款編號" width="180"> <template scope="scope"> <el-input v-if="scope.row.cashId=='#'" size="small" v-model="keyFrom.cashId" placeholder="請輸入內容"> <el-button slot="append" icon="search"></el-button> </el-input> <a href="javascript:;" @click="getDetali(scope.row.cashId)" v-else>{{scope.row.cashId}}</a> </template> </el-table-column>
第二種狀況是,好比回款狀態,能夠進行搜索的字段。可是是下拉搜索的
//修改前 <el-table-column label="回款狀態" width="200"> <template scope="scope"> <span v-if="scope.row.cashStatus === 0" class="color-red">待回款</span> <span v-if="scope.row.cashStatus === 1">部分回款</span> <span v-if="scope.row.cashStatus === 2" class="color-green">已回款</span> <span v-if="scope.row.cashStatus === 3" style="color: red">已取消</span> </template> </el-table-column> //修改後 <el-table-column label="回款狀態" width="100"> <template scope="scope"> <el-select v-model="keyFrom.cashStatus" size="small" placeholder="請選擇" v-if="scope.row.cashId=='#'" @change="search" :disabled="pageStatus!==null"> <el-option value="" label="全選"></el-option> <el-option value="0" label="待回款"></el-option> <el-option value="1" label="部分回款"></el-option> <el-option value="2" label="已回款"></el-option> <el-option value="3" label="已取消"></el-option> </el-select> <div v-else> <span v-if="scope.row.cashStatus === 0" class="color-red">待回款</span> <span v-if="scope.row.cashStatus === 1">部分回款</span> <span v-if="scope.row.cashStatus === 2" class="color-green">已回款</span> <span v-if="scope.row.cashStatus === 3" style="color: red">已取消</span> </div> </template> </el-table-column>
另外一種狀況是,好比回款流水號,不能夠進行搜索的字段。修改狀況是
//修改前 <el-table-column label="回款流水號" width="150"> <template scope="scope"> <span>{{scope.row.payNo}}</span> </template> </el-table-column> //修改後 <el-table-column label="回款流水號" width="150"> <template scope="scope"> <span v-if="scope.row.cashId!='#'">{{scope.row.payNo}}</span> </template> </el-table-column>
下面,我簡單說明下執行的流程。
1.filterModel
這個值,一開始設爲false
。
2.點擊按鈕,執行filterSearch
,因爲filterModel=false;
因此最後執行this.cashList.unshift({"cashId": "#"})
。
3.this.cashList這個數組,前面就添加了{"cashId": "#"}
。
點擊前
點擊後
4.this.cashList
第一條就變成了{"cashId": "#"}
,表格在遍歷到第一條的時候el-table-column
裏面,因爲**v-if**
的關係。排版就改變了!這就是數據驅動的魅力!
是搜索字段的第一行就變成了文本框
不是搜索字段的第一行就變成了空白的
5.交互就實現了!可是有一點要注意,就是搜索框v-model的值必定要綁定正確!
這個按鈕,大季家都知道是哪一個吧!就是這裏
/** * 開始搜索 */ search(){ this.getList(); },
沒看錯,就是這一行,代碼,由於每個文本框v-model了keyFrom相對應的值。因此,只要在文本輸入,keyFrom對應的值自動改!而後執行getList,keyFrom中,只要不是空字符或者null。就不會被過濾!這樣就至關於執行http://xxx.xxx.com/xxx/cash/l...的請求。至於爲何要令寫一個方法,不直接綁定getList呢,由於這裏還要觸發下面的搜索標籤。接下來會下面要說的!
看了搜搜索以後,我想你們都知道重置搜索怎麼作了!就是先把keyFrom搜索的屬性的值清空,再執行getList。
/** * @description 重置篩選條件 */ resetSearch(){ for (let key in this.keyFrom) { this.keyFrom[key] = null } this.getList(); }
搜索標籤,在不少地方都會見到過,就是給用戶看到,執行了什麼條件的搜索。
下面就實現下這個功能!
先實現,這個方法,這個方法,我想你們也已經知道了,就是遍歷keyFrom,而後把屬性和值遍歷道一個數組裏面,最後在html裏面v-for循環一下!
addTags(){ //tagsArr就是存放篩選標籤的數組,你們要在data裏面設置哦,初始值爲[]; let _this = this,_label,_value; //用一個變量,獲取清空keyFrom裏面值爲空的屬性! let _params = Object.assign(this.filterParams(this.keyFrom); //用一個變量,獲取_params屬性的集合! let _paramKeys = Object.keys(_params); //先清空tagsArr, this.tagsArr = []; _paramKeys.forEach((val) => { //根據val,設置_label標籤名 swicth(val){ case 'cashId':_label='回款編號';break; case 'ordId':_label='訂單編號';break; case 'custoName':_label='客戶名稱';break; case 'cashType':_label='回款類型';break; case 'cashStatus':_label='回款狀態';break; case 'userName':_label='採購人';break; case 'userMobile':_label='採購人電話';break; } //而後上面有提到到,好比回款狀態,這個的值是下拉搜索的。傳過來的值是狀態碼,並非文字。咱們主要手動把狀態碼轉譯成文字 //好比狀態嗎是0,咱們須要轉成‘待回款’ //若是val等於cashStatus,就是回款狀態,咱們須要轉譯 if (_key === 'cashStatus') { //判斷狀態碼 switch (_keyFrom3[_key]) { case '0': _value = "待回款"; break; case '1': _value = "部分回款"; break; case '2': _value = "已回款"; break; case '2': _value = "已取消"; break; } } //tagsArr添加元素! //_value若是爲真,就表明是把狀態碼轉成文字的,就添加_value,不然就直接添加_params[val] _this.tagsArr.push({ key: val, label: _label, value: _value||_params[val] }); }); },
這個方法何時觸發呢,就是在搜索和重置搜索的時候觸發 。這也解釋了爲何搜索要令寫一個方法!
search(){ this.getList(); this.addTags(); }, resetSearch(){ for (let key in this.keyFrom) { this.keyFrom[key] = null } this.getList(); this.addTags(); }
可是你們應該還有注意到一個,就是好比‘回款狀態’,是下拉搜索的,因此,在下拉框,就要綁定search方法。
而後在html頁面遍歷這個tagsArr。
眼尖的小夥伴又發現了,tagClose這個方法對吧!
接下來就實現這個!
tagClose(key, _index){ //根據下標,鼠標tagsArr數組某一項 this.tagsArr.splice(_index, 1); //根據key,把keyFrom某一項設爲空值 this.keyFrom[key] = null; //從新請求,更新cashList this.getList(); }
好了,今天就到這裏了,這篇文章也寫了將近10個小時了!若是你有耐心讀到這裏,你也是頗有耐心的勇士!固然,當面的代碼和交互仍是有細節是須要優化的,這個就比較簡單,小夥伴們,隨機應變下就知道怎麼作了!也寫累了!不想說太多了!下一篇文章,預熱就是利用監聽路由(vue-router)。來實現同一個頁面,不一樣狀態的處理。就好比:一樣是回款管理,我要求新建一個待回款的頁面,可是這個頁面只有待回款的數據。回款狀態也不能修改!這個小夥伴們也能夠試着作下,怎麼實現。這個相對簡單!
webpack+vue項目實戰(一,搭建運行環境和相關配置)
webpack+vue項目實戰(二,開發管理系統主頁面)
webpack+vue項目實戰(三,配置功能操做頁和組件的按需加載)