vue優化項目結構之service請求篇


敲代碼要有點逼格、要有點追求、

1.暴露問題

一般地,我們在vue項目中經常會用到vue-resource或者axios來進行網絡數據請求、剛接觸不久的同學會很自然的直接調用其api來進行請求,例如:

這種將url直接寫死的,直接拖出去打死吧、【如果服務地址發生變化,整個項目接口都需要去更改】

 這種稍微好點的,知道將地址配成一個全局變量。【總感覺還是太過累贅,而且並不能直觀反應這段請求的目的是做什么的】

2.思考我們需要怎么做

理想狀況下,我們希望在需要調用接口的時候直接調用一個方法,傳入參數,然后拿到數據,類似這樣:

【方法名很直觀,沒有暴露出接口地址,代碼不會亂】

3.vue項目結構升級

a.這里我們將抽離出service來管理各個模塊的請求;

b.將抽離出一個文件api.js來統一管理請求接口的地址;

c.並將axios或者vue-resource的請求做一個封裝http.js,方便調用;

首先看一下完整結構:

先看一下http.js:

  1 /**
  2  * http utils, provide general check for http response
  3  */
  4 
  5 axios.defaults.headers.post['Content-Type'] = 'application/json'
  6 axios.defaults.withCredentials = true
  7 
  8 axios.interceptors.request.use(function (config) {
  9     // 動態設置參數
 10     //config.headers = Object.assign(config.headers || {}, {accessToken: '63F5640A1FE54E22A53AA8879373CEB8'})
 11 
 12     // config.params = Object.assign(config.params || {}, {deviceType: 'wap'})
 13 
 14     return config
 15 
 16 }, function (error) {
 17     // Do something with request error
 18     return Promise.reject(error)
 19 })
 20 
 21 const getSettings= () => {
 22     return axios.defaults // 返回 axios 配置對象供外部設置或自定義特殊處理
 23 }
 24 
 25 const checkHttp = (res) => {
 26     if (!res) {
 27         let errObj = {
 28             message: '響應數據為空',
 29             response: null
 30         }
 31 
 32         throw errObj
 33     }
 34 
 35     let status = res.status
 36     if (status === 200) {
 37         return res.data
 38     }
 39 
 40     let errObj = {
 41         message: '請求錯誤',
 42         response: res
 43     }
 44 
 45     throw errObj
 46 }
 47 
 48 const checkResult = (res) => {
 49     let data = checkHttp(res)
 50     var ua = navigator.userAgent.toLowerCase();
 51     if (data.retCode == '1000') {
 52 
 53         return data
 54     }
 55 
 56 
 57     if (data.retCode == '2005'){
 58         if(ua.match(/MicroMessenger/i)=="micromessenger") {
 59 
 60             window.location = "http://www.ucaigou.net/weixin/user/auth?autoCreateUserFlag=0&gotoUrl=http://mobile.ucaigou.net"
 61             return
 62         } else {
 63 
 64             return
 65         }
 66     }
 67 
 68     let errObj = {
 69         message: data.retMsg || '請求錯誤',
 70         response: res
 71     }
 72 
 73     throw errObj
 74 }
 75 
 76 export const get = (url, params, headers) => {
 77     return axios.get(url, {params, headers}).then(checkResult)
 78 }
 79 
 80 export const post = (url, data, headers) => {
 81     return axios.post(url, data, headers).then(checkResult)
 82 }
 83 
 84 export const formPost = (url, params) => {
 85     axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
 86     let formData = ""
 87     if(params) {
 88         for (var key in params) {
 89             formData += key + "=" + params[key] + "&"
 90         }
 91     }
 92     return axios.post(url, formData).then(checkResult)
 93 }
 94 
 95 export const put = (url, data) => {
 96     return axios.put(url, data).then(checkResult)
 97 }
 98 
 99 export const del = (url) => {
100     return axios.delete(url)
101 }
102 
103 /**
104  * raw json request
105  */
106 export const getJson = (url, params) => {
107     return axios.get(url, params).then(checkHttp)
108 }
109 
110 export default {get, post,formPost, put, del, getJson, getSettings}

【這段代碼可以提出來公用,其實也就是對axios的各種方法進行提取封裝】

 

看看api.js文件:

 4 import {devMode} from 'utils/env'
 5 const DEFAULT_API_BASE = devMode ? '/' : '//www.xxxxxx.net/'
 6 
 7 const _dataPath = (url) => {
 8     return `${DEFAULT_API_BASE}/${url}`
 9 }
10 
11 /**
12  * API請求參數和響應內容的具體說明可參考
13  * 
14  */
15 export default {
16     PROV_CITY_DICT: _dataPath('api/provCityDist'), // 省市區查詢
17     TOWN_DICT: _dataPath('api/town'), // 區縣(四級地址)查詢
18     CATEGORY_LIST: _dataPath('api/product/category'), // 商品分類查詢
19     PRODUCT_LIST: _dataPath('api/product/list'), // 商品列表查詢
20     PRODUCT_DETAIL: _dataPath('api/product/detail'), // 商品詳情查詢
21     HOME_BANNER_LIST: _dataPath('api/home/banner/list'), // banner位
22     HOME_SCENE_LIST: _dataPath('api/home/scene/list'), // 場景采購(高校采購場景方案)
23     HOME_FLOOR_LIST: _dataPath('api/home/floor/list'), // 樓層數據
24     RECOMMEND_PRODUCT_LIST:_dataPath('api/product/recommend'), // 推薦商品列表
25     PRODUCT_KEYWORD_SUGGEST:_dataPath('api/product/suggest'), // 商品關鍵詞聯想
26     ADDR_ADD: _dataPath('api/address/add'), // 用戶地址添加
27     ADDR_DEL: _dataPath('api/address/delete'), // 用戶地址刪除
28     ADDR_UPDATE: _dataPath('api/address/update'), // 用戶地址更新
29     ADDR_LIST: _dataPath('api/address/list'), // 用戶全部地址查詢
30     ADDR_QUERY: _dataPath('api/address/query'), // 用戶地址查詢
31     ADDR_DEFAULT: _dataPath('api/address/default'), // 獲取用戶默認收貨地址
32     CART_ADD: _dataPath('api/shoppingCart/add'), // 購物車添加
33     CART_QUERY: _dataPath('api/shoppingCart/query'), // 購物車列表查詢
34     CART_UPDATE: _dataPath('api/shoppingCart/update'), // 購物車更新數量
35     CART_DEL: _dataPath('api/shoppingCart/delete'), // 購物車刪除
36      .........
37 
38 
39 }

【這段代碼將項目中用到的所有接口地址全部進行了配置】

接下來看看service文件:

 1 import http from 'utils/http'
 2 import api from 'api'
 3 
 4 
 5 /**
 6  * 訂單列表
 7  */
 8 
 9 
10 export const orderList = async (params) => {
11     const sendParams = Object.assign({ // 默認參數
12         "pageNum": 1,
13         "pageSize": 15,
14     }, params)
15 
16     return http.post(api.ORDER_LIST, sendParams)
17 }
18 
19 
20 /**
21  * 訂單詳情
22  */
23 
24 export const orderDetail = async (params) => {
25     return http.get(`${api.ORDER_DETAIL}?id=${params}`)
26 }
27 
28 
29 /**
30  * 查看物流
31  */
32 
33 export const orderEpress = (params) => {
34     return http.post(api.ORDER_EXPRESS, params)
35 }

【導入http.js、api.js,可以看到每一個service方法都返回一個promise對象】

使用方法:

import {orderList,cancleOrder,orderRecevce} from 'services/order.service'

【使用時導入需要用到的方法,並調用】

完結、

 


免責聲明!

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



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