消息提示框封裝:
//消息提示框封裝 /** // 提示的內容 title: '消息提示框', // 提示的內容 icon: 'success', // 提示的圖標,success(成功)、error(失敗)、loading(加載)、none(不顯示圖標) duration: 2000, // 提示的延遲時間 mask: true // 是否顯示透明蒙層,防止觸摸穿透 */ const toast = ({ title = '數據加載中', icon = 'none', mask = true, duration = 3000 } = {}) => { wx.showToast({ title, icon, mask, duration }) } //掛載到全局 wx.toast=toast; //導出 export {toast}
調用
//import {toast} from './utils/extendApi' import './utils/extendApi' //toast() //toast({"title":"成功","icon":"success"}) //wx.toast(); wx.toast({"title":"成功","icon":"success"})
----------------------------------------------------------漂亮的分割線----------------------------------------------------------------------------------------
消息對話框封裝:
wx.showModal({ title: '提示', // 提示的標題 content: '您確定執行該操作嗎?', // 提示的內容 confirmColor: '#f3514f', // 接口調用結束的回調函數(調用成功、失敗都會執行) complete({ confirm, cancel }) { confirm && console.log('點擊了確定') cancel && console.log('點擊了取消') } })
封裝
const modal = (options = {}) => { // 使用 Promise 處理 wx.showModal 的返回結果 return new Promise((resolve) => { // 默認的參數 const defaultOpt = { title: '提示', content: '您確定執行該操作嗎?', confirmColor: '#f3514f', } // 將傳入的參數和默認的參數進行合併 const opts = Object.assign({}, defaultOpt, options) wx.showModal({ // 將合併的參數賦值傳遞給 showModal 方法 ...opts, complete({ confirm, cancel }) { // 如果用戶點擊了確定,通過 resolve 拋出 true // 如果用戶點擊了取消,通過 resolve 拋出 false confirm && resolve(true) cancel && resolve(false) } }) }) } wx.modal = modal //導出 export { modal }
如果全局使用:export const modal = (options = {}) => {
刪除:export { toast,modal }
使用:
import {modal} from './utils/extendApi' //import './utils/extendApi' App({ async onShow(){ // 第一種調用方式:不傳入任何參數 // 不使用任何參數,使用默認值 //const res = await modal() //console.log(res) // 第二種調用方式:更改默認配置 const res = await modal({ content: '鑑權失敗,請重新登錄', showCancel: false }) console.log(res) } })
----------------------------------------------------------漂亮的分割線----------------------------------------------------------------------------------------
封裝本地存儲
/** * @description 存儲數據 * @param {*} key 本地緩存中指定的 key * @param {*} value 需要緩存的數據 */ export const setStorage = (key, value) => { try { wx.setStorageSync(key, value) } catch (e) { console.error(`存儲指定 ${key} 數據發生錯誤:`, e) } } /** * @description 從本地讀取對應 key 的數據 * @param {*} key */ export const getStorage = (key) => { try { const value = wx.getStorageSync(key) if (value) { return value } } catch (e) { console.error(`獲取指定 ${key} 數據發生錯誤:`, e) } } /** * @description 從本地移除指定 key 數據 * @param {*} key */ export const removeStorage = (key) => { try { wx.removeStorageSync(key) } catch (e) { console.error(`移除指定 ${key} 數據發生錯誤:`, e) } } /** * @description 從本地清空全部的數據 */ export const clearStorage = () => { try { wx.clearStorageSync() } catch (e) { console.error("清空本地存儲時發生錯誤:", e); } } /** * @description 將數據存儲到本地 - 異步方法 * @param {*} key 本地緩存中指定的 key * @param {*} data 需要緩存的數據 */ export const asyncSetStorage = (key, data) => { return new Promise((resolve) => { wx.setStorage({ key, data, complete(res) { resolve(res) } }) }) } /** * @description 從本地讀取指定 key 的數據 - 異步方法 * @param {*} key */ export const asyncGetStorage = (key) => { return new Promise((resolve) => { wx.getStorage({ key, complete(res) { resolve(res) } }) }) } /** * @description 從本地移除指定 key 的數據 - 異步方法 * @param {*} key */ export const asyncRemoveStorage = (key) => { return new Promise((resolve) => { wx.removeStorage({ key, complete(res) { resolve(res) } }) }) } /** * @description 從本地移除、清空全部的數據 - 異步方法 */ export const asyncClearStorage = () => { return new Promise((resolve) => { wx.clearStorage({ complete(res) { resolve(res) } }) }) }
調用:
import {setStorage,getStorage,removeStorage,clearStorage,asyncSetStorage,asyncGetStorage} from './utils/storage' App({ async onShow(){ setStorage('name','張三') let _name= getStorage('name') console.log(_name) asyncSetStorage('age',28).then((res)=>{ console.log(res.errMsg) }) asyncGetStorage('age').then((res)=>{ console.log(res.data) }) } })
----------------------------------------------------------漂亮的分割線----------------------------------------------------------------------------------------
網絡請求封裝
// 創建 WxRequest 類 // 通過類的方式來進行封裝,會讓代碼更加具有複用性 // 也可以方便添加新的屬性和方法 class WxRequest { // 定義實例屬性,用來設置默認請求參數 defaults = { baseURL: '', // 請求基準地址 url: '', // 接口的請求路徑 data: null, // 請求參數 method: 'GET', // 默認的請求方法 // 請求頭 header: { 'Content-type': 'application/json' // 設置數據的交互格式 }, timeout: 60000, // 默認的超時時長,小程序默認的超時時長是 1 分鐘 isLoading: true // 控制是否使用默認的 loading,默認值是 true 表示使用默認的 loading } // 定義攔截器對象 // 需要包含請求攔截器以及響應攔截器,方便在請求之前以及響應以後時進行邏輯處理 interceptors = { // 請求攔截器 // 在請求發送之前,對請求參數進行新增或者修改 request: (config) => config, // 響應攔截器 // 在服務器響應數據以後,對服務器響應的數據進行邏輯處理 response: (response) => response } // 定義數組隊列 // 初始值需要是一個空數組,用來存儲請求隊列、存儲請求標識 queue = [] // 用於創建和初始化類的屬性以及方法 // 在實例化時傳入的參數,會被 constructor 形參進行接收 constructor(params = {}) { // 通過 Object.assign 方法合併請求參數 // 注意:需要傳入的參數,覆蓋默認的參數,因此傳入的參數需要放到最後 this.defaults = Object.assign({}, this.defaults, params) } // request 實例方法接收一個對象類型的參數 // 屬性值和 wx.request 方法調用時傳遞的參數保持一致 request(options) { // 如果有新的請求,就清除上一次的定時器 this.timerId && clearTimeout(this.timerId) // 注意:需要先合併完整的請求地址 (baseURL + url) // https://gmall-prod.atguigu.cn/mall-api/index/findBanner options.url = this.defaults.baseURL + options.url // 合併請求參數 options = { ...this.defaults, ...options } // 在請求發送之前,添加 loading 效果 // wx.showLoading() if (options.isLoading && options.method !== 'UPLOAD') { // 判斷 queue 隊列是否爲空,如果是空,就顯示 loading // 如果不是空,就不顯示 loading,不調用 wx.showLoading() this.queue.length === 0 && wx.showLoading() // 然後立即向 queue 數組隊列中添加請求標識 // 每個標識代表是一個請求,標識是自定義的 this.queue.push('request') } // 在請求發送之前,調用請求攔截器,新增和修改請求參數 options = this.interceptors.request(options) // 需要使用 Promise 封裝 wx.request,處理異步請求 return new Promise((resolve, reject) => { if (options.method === 'UPLOAD') { wx.uploadFile({ ...options, success: (res) => { // 需要將服務器返回的 JSON 字符串 通過 JSON.parse 轉成對象 res.data = JSON.parse(res.data) // 合併參數 const mergeRes = Object.assign({}, res, { config: options, isSuccess: true }) resolve(this.interceptors.response(mergeRes)) }, fail: (err) => { // 合併參數 const mergeErr = Object.assign({}, err, { config: options, isSuccess: false }) reject(this.interceptors.response(mergeErr)) } }) } else { wx.request({ ...options, // 當接口調用成功時會觸發 success 回調函數 success: (res) => { // 不管是成功響應還是失敗響應,都需要調用響應攔截器 // 響應攔截器需要接收服務器響應的數據,然後對數據進行邏輯處理,處理好以後進行返回 // 然後在通過 resolve 將返回的數據拋出去 // 在給響應攔截器傳遞參數時,需要將請求參數也一起傳遞 // 方便進行代碼的調試或者進行其他邏輯處理,需要先合併參數 // 然後將合併的參數傳遞給響應攔截器 // 不管是請求失敗還是請求成功,都已經將響應的數據傳遞給了響應攔截器 // 這時候在合併參數的時候,追加一個屬性:isSuccess // 如果屬性值爲 true,說明執行了 success 回調函數 // 如果屬性值爲 false,說明執行了 fail 回調函數 const mergeRes = Object.assign({}, res, { config: options, isSuccess: true }) resolve(this.interceptors.response(mergeRes)) }, // 當接口調用失敗時會觸發 fail 回調函數 fail: (err) => { // 不管是成功響應還是失敗響應,都需要調用響應攔截器 const mergeErr = Object.assign({}, err, { config: options, isSuccess: false }) reject(this.interceptors.response(mergeErr)) }, // 接口調用結束的回調函數(調用成功、失敗都會執行) complete: () => { if (options.isLoading) { // 在每一個請求結束以後,都會執行 complete 回調函數 // 每次從 queue 隊列中刪除一個標識 this.queue.pop() this.queue.length === 0 && this.queue.push('request') this.timerId = setTimeout(() => { this.queue.pop() // 在刪除標識以後,需要判斷目前 queue 數組是否爲空 // 如果是空,說明併發請求完成了 // 就需要隱藏 loading,要調用 wx.hideLoading() this.queue.length === 0 && wx.hideLoading() clearTimeout(this.timerId) }, 1) // 不管請求時成功還是失敗,都需要隱藏 loading // wx.hideLoading() } } }) } }) } // 封裝 GET 實例方法 get(url, data = {}, config = {}) { // 需要調用 request 請求方法發送請求,只需要組織好參數,傳遞給 request 請求方法即可 // 當調用 get 方法時,需要將 request 方法的返回值 return 出去 return this.request(Object.assign({ url, data, method: 'GET' }, config)) } // 封裝 DELETE 實例方法 delete(url, data = {}, config = {}) { return this.request(Object.assign({ url, data, method: 'DELETE' }, config)) } // 封裝 POST 實例方法 post(url, data = {}, config = {}) { return this.request(Object.assign({ url, data, method: 'POST' }, config)) } // 封裝 PUT 實例方法 put(url, data = {}, config = {}) { return this.request(Object.assign({ url, data, method: 'PUT' }, config)) } // 用來處理併發請求 all(...promise) { // 通過展開運算符接收傳遞的參數 // 那麼展開運算符會將傳入的參數轉成數組 // console.log(promise) return Promise.all(promise) } /** * @description upload 實例方法,用來對 wx.uploadFile 進行封裝 * @param {*} url 文件的上傳地址、接口地址 * @param {*} filePath 要上傳的文件資源路徑 * @param {*} name 文件對應的 key * @param {*} config 其他配置項 */ upload(url, filePath, name = 'file', config = {}) { return this.request( Object.assign({ url, filePath, name, method: 'UPLOAD' }, config) ) } } export default WxRequest
----------------------------------------------------------漂亮的分割線----------------------------------------------------------------------------------------
mina-request的安裝
網站:mina-request - npm (npmjs.com)
安裝命令:npm install mina-request
工具——>構建npm
http.js
// 導入模塊、包提供的類 import WxRequest from 'mina-request' // 導入封裝的本地存儲操作模塊 import { getStorage, clearStorage } from './storage' // 導入封裝的增強 API import { toast, modal } from './extendApi' // 對類進行實例化 const instance = new WxRequest({ baseURL: 'https://gmall-prod.atguigu.cn/mall-api', timeout: 15000 }) // 添加請求攔截器 (在請求發送之前對請求參數進行新增或者修改) instance.interceptors.request = (config) => { // 在實際開發中,有一些接口需要使用訪問令牌 token // 訪問令牌 token 通常是存儲到本地 // 需要先從本地獲取到存儲的 token const token = getStorage('token') // 如果本地存在 token,這時候就需要在請求頭中添加 token 字段 if (token) { config.header['token'] = token } // 在發送請求之前做些什麼 return config } // 添加響應攔截器 (在服務器響應數據以後,對返回的數據進行邏輯處理) instance.interceptors.response = async (response) => { // 從 response 對象中解構兩個數據 const { isSuccess, data } = response // response 服務器響應的數據,只不過數據被 wx.request 進行了一層包裝 // console.log(response) // response.config 封裝的包裏面提供的 config 屬性,是請求的參數信息 // 可以使用請求參數進行代碼的調試 // response.data 服務器真正響應的數據 // response.isSuccess 判斷代碼執行了哪一個回調函數 // isSuccess = true,說明代碼執行了 wx.request 方法的 success 回調函數 // isSuccess = false,說明代碼執行了 wx.request 方法的 fail 回調函數 // 如果 isSuccess = false,說明網絡出現了問題 if (!isSuccess) { toast({ title: '網絡異常請重試', icon: 'error' }) return Promise.reject(response) } // 如果 isSuccess = true,說明代碼執行到了 success 回調函數 // 需要開發者對返回的參數進行邏輯判斷 // 需要對後端返回的業務狀態碼進行判斷 // 業務狀態碼 === 200,接口調用成功,服務器成功返回了數據 // 業務狀態碼 === 208,沒有 token 或者 token 失效,需要讓用戶重新進行登錄 // 業務狀態碼既不等於 200,也不等於 208,說明出現了其他異常,需要給用戶統一進行提示 switch (data.code) { case 200: // 接口調用成功,服務器成功返回了數據,只需要將數據簡化以後返回即可 return data case 208: const res = await modal({ content: '鑑權失敗,請重新登錄', showCancel: false }) if (res) { // 既然用戶需要重新進行登錄,就需要把之前用戶存儲的信息(過期的 token) 進行清除 clearStorage() wx.navigateTo({ url: '/pages/login/login' }) } return Promise.reject(response) default: toast({ title: '程序出現異常,請聯繫客服或稍後重試!' }) return Promise.reject(response) } // return response } // 導出實例 export default instance
接口地址環境變量設置
添加env.js
// 獲取 小程序帳號信息 const { miniProgram } = wx.getAccountInfoSync() // 獲取小程序當前開發環境 // develop 開發版, trial 體驗版, release 正式版 const { envVersion } = miniProgram let env = { baseURL: 'https://gmall-prod.atguigu.cn' } switch (envVersion) { //開發版 case 'develop': env.baseURL = 'https://gmall-prod.atguigu.cn' break //體驗版 case 'trial': env.baseURL = 'https://gmall-prod.atguigu.cn' break //正式版 case 'release': env.baseURL = 'https://gmall-prod.atguigu.cn' break defaulr } export { env }
http.js
// 導入模塊、包提供的類 import WxRequest from 'mina-request' // 導入封裝的本地存儲操作模塊 import { getStorage, clearStorage } from './storage' // 導入封裝的增強 API import { toast, modal } from './extendApi' import {env} from './env' // 對類進行實例化 const instance = new WxRequest({ //baseURL: 'https://gmall-prod.atguigu.cn/mall-api', baseURL:env.baseURL, timeout: 15000, isLoading:false })
模塊API封裝
index.js
// 導入封裝的網絡請求工具 http.js import http from '../utils/http' /** * @description 獲取輪播圖數據 * @returns Promise */ export const reqSwiperData = () => http.get('/mall-api/index/findBanner')
// 導入接口 API import { reqSwiperData } from '../../api/index' Page({ // 頁面數據 data: { swiperList: [] }, // 小程序頁面加載時執行 onLoad () { // 調用獲取首頁數據的方法 getHomeList() } // 獲取首頁數據 async getHomeList() { // 獲取輪播圖數據 const res = await reqSwiperData() console.log(res) } })