02_微信小程序常用的方法封装

 

消息提示框封装:

//消息提示框封装
/**
// 提示的内容
  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)
      }
    })
  })
}
View Code

 

调用:

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

 

posted @ 2024-04-22 14:05  野码  阅读(576)  评论(0编辑  收藏  举报