webpack+vue項目實戰(四,前端與后端的數據交互和前端展示數據)


地址:https://segmentfault.com/a/1190000010063757

1.前言

今天要做的,就是在上一篇文章的基礎上,進行功能頁面的開發。簡單點說呢,就是與后端的數據交互和怎么把數據展示出來,用到的資源主要是element-ui和vue-resource,其它參考(vue-resource插件使用)。今天講到的一些功能開發,主要就是請求列表數據,詳情數據,分頁功能操作,搜索,搜索標簽等的開發。今天這個,按照下面步驟,一步一步來。一個一個功能的做!

2.數據接口

我以‘回款管理’(cashList.vue)為開發的demo,下文講到的各種增刪改查都是在這個文件上操作,大家注意喔!這雖然是做5個功能,其實就只有兩個接口。(按照我開發項目,后端提供的接口說明)

2-1分析接口

下面分析下我們公司后端給我提供的其中兩個接口。而且兩個接口都是get請求。

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.回款編號(必填) **/

2-2整理數據

首先,由於接口http_url.list接口可以接受一些搜索,先把整個准備了!

然后再到頁碼的一些東西,主要是三個,當前頁碼,每頁條數。(自己隨便設的默認值)
數據就變成了

data(){
    return {  pageSize:10,//每頁條數  allCount:0,//記錄總數  currentPage:1,//當前頁碼  cashList: [], //列表數組(現在是准備請求接口,不需要模擬的數據,所以設置一個空數組)  keyFrom: {....}//搜索字段 } } 

大家可能不明白,同樣是請求的參數,頁碼這些為什么要和搜索字段分開放?之所以分開放是因為頁碼這些,到下面分頁的時候要單獨使用,而且做搜索的時候,頁碼又不是搜索字段,所以就分開放,下面會詳情的說明!

准備就准備這么多了,之后還要用到什么數據,以后再添加!

3.請求列表數據

先別急着寫,大家可以想下,搜索字段那里,比如我只想根據回款ID(cashId)查詢呢?
難道這樣發送請求?http://xxx.xxx.com/xxx/cash/l...''&cashId=xxx&custoName=''&cashType=''&cashStatus=''&userName=''&userMobile=''
真沒必要,我們想要的是這樣http://xxx.xxx.com/xxx/cash/l...
所以,請求之前,先寫一個方法,就是過濾搜索字段(keyFrom)里面,值為空的屬性。

/** * 清除對象中值為空的屬性 */ 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; } 

3-1請求列表數據

   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) { }); } 

3-2寫完之后,在mounted運行這方法。

mounted(){
    this.getList(); }, 

為了能更直觀看到結果,我在瀏覽器直接打開這個接口

需要的有的字段都有了
那么接下來就接收返回的字段

    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); } }); }

3-3在html頁面鋪數據

怎么鋪,隨機應變唄!
來到el-table這個標簽這里。不知道排版布局的話,參考上一篇文章喔!不要不知道我在說什么!


然后開始寫<el-table-column></el-table-column>

下面簡單寫幾個栗子

3-3-1回款id

點擊回款id,會出來詳情頁面(詳情頁面的方法getDetail我們到下面寫,現在)

<el-table-column label="編號" width="180"> <template scope="scope"> <a href="javascript:;">{{scope.row.cashId}}</a> </template> </el-table-column> 

3-3-2訂單id

訂單id只需要顯示,就簡單了

<el-table-column label="訂單編號" width="160"> <template scope="scope"> <span>{{ scope.row.ordId }}</span> </template> </el-table-column>

3-3-3回款時間

回款時間需要把時間戳轉成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, '-')}}&nbsp;{{new Date(scope.row.cashDate).toTimeString().split(' ')[0]}}</span> </div> </template> </el-table-column> 

3-3-4回款狀態

回款狀態需要把狀態碼轉換成文字

<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>

3-3-5回款金額

金額在數據庫以分為單位,現在需要轉換成元

<el-table-column label="回款金額(元)" width="150"> <template scope="scope"> <span>{{ (scope.row.cashAmount / 100).toFixed(2) }}</span> </template> </el-table-column> 

3-3-6細節優化

好了,典型的幾種數據,以及處理的方法,就是在這里了。當然這個只是做展示作用,怎么展示是看項目的需求的!
小伙伴們運行起來的時候,可能會發現兩個問題。

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); } }); }

然后我們就會看到這樣的結果,就明確的說明了,這里的值為空

4.請求詳情數據

詳情的數據,就是點擊列表的任何一條數據,出來一個詳情頁面。

先在瀏覽器請求一下(看下有身什么字段,可以方便在html里面鋪數據),看到有很多字段。

詳情的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) },

5.分頁

分頁這個功能,大家可能都接觸過,寫得也是很復雜。但是今天用了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這個數組就更新了。我們分頁就開發完了。

6.搜索功能

搜索功能這個太常見了,我現在做的項目,搜索需求就是。

然后輸入再點擊

交互很容易理解。就是輸入,然后再輸出結果,如上圖,我在回款ID下面的文本框輸入‘M2017070400060002’。然后點擊搜索。就會出現輸出結果。
下面,我們一步步來

6-1點擊,出現搜索框。

6-1-1,找到這個按鈕,在這個按鈕上綁定一個方法

6-1-2.編寫filterSearch這個方法,代碼如下

/** * 顯示與隱藏搜索 */ filterSearch(){ //filterModel小伙伴們要在data上聲明哦,初始值為false。這個值是記錄當前是不是要顯示搜索框,進行搜索的。 //當前是否需要搜索狀態 if (this.filterModel) { this.cashList.splice(0, 1); } else { this.cashList.unshift({ "cashId": "#", }) } //顯示或隱藏搜索 this.filterModel = !this.filterModel; }

6-1-3.列表的改造

首先,清楚一個。后端返回的數據(如上圖),並不是所有的字段都是可以進行搜索的字段。只有這幾個字段(如下圖),才可以進行搜索。

所以,這里我分三種請況。

一種情況是,比如回款編號,可以進行搜索的字段。

 //修改前 <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> 

6-1-4流程說明

下面,我簡單說明下執行的流程。
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的值一定要綁定正確!

6-2實現搜索功能

6-2-1.首先,在每個按鈕里面,都綁定一個點擊事件,綁定search方法,用來啟動搜索!


這個按鈕,大季家都知道是哪個吧!就是這里

6-2-2.然后,編寫search方法

/** * 開始搜索 */ search(){ this.getList(); }, 

沒看錯,就是這一行,代碼,因為每一個文本框v-model了keyFrom相對應的值。所以,只要在文本輸入,keyFrom對應的值自動改!然后執行getList,keyFrom中,只要不是空字符或者null。就不會被過濾!這樣就相當於執行http://xxx.xxx.com/xxx/cash/l...的請求。至於為什么要令寫一個方法,不直接綁定getList呢,因為這里還要觸發下面的搜索標簽。接下來會下面要說的!

6-3實現重置搜索功能

看了搜搜索之后,我想大家都知道重置搜索怎么做了!就是先把keyFrom搜索的屬性的值清空,再執行getList。

/** * @description 重置篩選條件 */ resetSearch(){ for (let key in this.keyFrom) { this.keyFrom[key] = null } this.getList(); } 

7.搜索標簽

搜索標簽,在很多地方都會見到過,就是給用戶看到,執行了什么條件的搜索。
下面就實現下這個功能!

7-1.編寫方法

先實現,這個方法,這個方法,我想大家也已經知道了,就是遍歷keyFrom,然后把屬性和值遍歷道一個數組里面,最后在html里面v-for循環一下!

7-2-1添加標簽

    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方法。

7-2-2html頁面遍歷

然后在html頁面遍歷這個tagsArr。

7-2-3刪除標簽

眼尖的小伙伴又發現了,tagClose這個方法對吧!
接下來就實現這個!

tagClose(key, _index){
    //根據下標,鼠標tagsArr數組某一項 this.tagsArr.splice(_index, 1); //根據key,把keyFrom某一項設為空值 this.keyFrom[key] = null; //重新請求,更新cashList this.getList(); }

8.未完待續

好了,今天就到這里了,這篇文章也寫了將近10個小時了!如果你有耐心讀到這里,你也是很有耐心的勇士!當然,當面的代碼和交互還是有細節是需要優化的,這個就比較簡單,小伙伴們,隨機應變下就知道怎么做了!也寫累了!不想說太多了!下一篇文章,預熱就是利用監聽路由(vue-router)。來實現同一個頁面,不同狀態的處理。就比如:同樣是回款管理,我要求新建一個待回款的頁面,但是這個頁面只有待回款的數據。回款狀態也不能修改!這個小伙伴們也可以試着做下,怎么實現。這個相對簡單!

9.往期占坑

webpack+vue項目實戰(一,搭建運行環境和相關配置)
webpack+vue項目實戰(二,開發管理系統主頁面)
webpack+vue項目實戰(三,配置功能操作頁和組件的按需加載)


免責聲明!

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



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