最新时时彩平台演示 中新时时彩要不要交税 新时时彩三星组六技巧 最新时时彩源码修改 新时时彩遗漏走势图 新时时彩预测方法 新时时彩计算器 新时时彩开奖皇冠网址 新时时彩组三怎么玩 最新时时彩后四稳赚 新时时彩官方开奖网站 新时时彩人工计划 新时时彩开奖漏洞 新时时彩最长遗漏 新时时彩中奖顺序 360新时时彩技巧-轴承资讯 新时时彩停售 最新时时彩杀号高手 新时时彩三星走势图 玩新时时彩有什么技巧 新时时彩3星和尾走势 新时时彩后一公式 重新时时彩网站 新时时彩遗漏统计软件 吉林新时时彩走势图 新时时彩中奖怎么查 新时时彩是什么地方 新时时彩中奖怎么查 新时时彩下载手机版下载 新时时彩贴吧 最新时时彩计划软件 大赢家新时时彩 新时时彩注册送彩金 新时时彩组选投注技巧 新时时彩走势图 新时时彩万能5码 新时时彩模拟 新疆新时时彩往期开奖号码 新时时彩的玩法 新时时彩稳赚计划 最新时时彩70注 新时时彩返奖率 新时时彩杀号定胆360 新时时彩后二杀号 新时时彩振幅走势 最新时时彩教程 新时时彩后台软件 新时时彩几点开始 新时时彩日赚几百 最新时时彩注册送20
用户
 ?#19968;?#23494;码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,登录网站

小程序社区 首页 教程 查看内容

微信小程序开发中的代码片段总结

Rolan 2019-3-22 00:34

经过一段时间的微信小程序开发,总结了一些代码片段,主要是以下几个方面:小程序(授权、网络、录音、图像)mpvue(分包、全局变量、svg组件、组件class绑定)小程序授权逻辑初次请求 - 请求用户授权 - 同意授权(- ...

经过一段时间的微信小程序开发,总结了一些代码片段,主要是以下几个方面:

  • 小程序(授权、网络、录音、图像)
  • mpvue(分包、全局变量、svg组件、组件class绑定)

小程序

授权逻辑

  1. 初次请求 -> 请求用户授权 -> 同意授权(-> 不同意授权 -> 结束) -> 使用对应功能
  2. 二次请求 -> 跳转小程序设置页面modal -> 设置页面 -> 开启scope -> 使用对应功能
const checkPermission = scope =>
  new Promise((resolve, reject) => {
    wx.getSetting({
      success: res => {
        // 是否存在认证配置
        let hasAuthorized = res.authSetting.hasOwnProperty(scope)
        if (hasAuthorized) {
          // 已授权
          if (res.authSetting[scope]) {
            resolve('已授权')
            return
          }
          // 未授权,提示进入小程序设置页面,wx限制:需要主动点击才能执行openSetting(),因此使用modal
          wx.showModal({
            title: '没有权限',
            content: '体验该功能需要您授权功能权限,现在前往设置开启',
            success: res => {
              if (res.confirm) {
                reject('设置页面')
                wx.openSetting()
              } else if (res.cancel) {
                reject('不进入设置')
              }
            }
          })
        }
      },
      fail: err => { reject(err.errMsg) }
    })
  })

网络

微信小程序不同环境下网络请求的不同之处:

校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书

网络请求与拦截器

可以使用 fly.js 作为小程序的网络请求库,在使用拦截器等功能时?#27493;?#20026;方便。

小程序中一个特殊的地方是: content-type 为 multipart/formdata 类型的POST请求不能通过自定义请求的方式发出,需要使用小程序的 wx.uploadFile 方法,可以如下简单封装下:

const formDataRequest = (url, filePath, params = {}) =>
  new Promise((resolve, reject) => {
    let token = wx.getStorageSync("token")
    wx.uploadFile({
      url,
      filePath,
      name: "file",
      header: { token },
      formData: params,
      success: async res => {
        // 一些对响应数据的处理...
        resolve(res.data)
      },
      fail: err => {
        reject(err)
      }
    });
  });

判断是否在线

使用 getNetworkType 方法即可

export const isOnline = () =>
  new Promise((resolve, reject) => {
    wx.getNetworkType({
      success(res) {
        const networkType = res.networkType
        resolve(networkType !== 'none')
      },
      failed(res) {
        reject(res)
      }
    })
  })

录音处理

主要是录音时的API检测、状态控制与?#24405;?#30417;听器的处理。

// 1. 检测录音管理器是否可用
if (wx.getRecorderManager) {
  this.recorder = wx.getRecorderManager()
  this.addRecorderListener()
} else {
  wx.showModal({
    title: '提示',
    showCancel: false,
    content:
      '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
  })
}
// 2. 录音前检测scope.record授权情况
async startRecordHandle() {
  if (!this.recorder) return
  try { await this.checkPermission('scope.record') }  
  catch (err) { return }
  this.recorder.start(this.audioOption)
},
// 3. 添加?#24405;?#30417;听器
addRecorderListener() {
  if (!this.recorder) return
  this.recorder.onStart(() => {
    ...
    this.recording = true
  })
  this.recorder.onStop(path => {
    ...
    this.recording = false
    this.audioPath = path.tempFilePath
  })
}

若需实现长按录音的场景,可以结合 lonepress ?#24405;?#19982; setTimeout 来实现。

<template>
  <g-button type="primary"
    ...
    @long-press="longPressHandle"
  />
</template>
<script>
export default {
  methods: {
    longPressHandle() {
      // longpress?#24405;?#20250;在350ms后出发
      this.canRecordStart = true
    },
    touchStartHandle() {
      this.canRecordStart = true
      let delay = 400 // 设置400ms延迟
      setTimeout(() => {
        if (this.canRecordStart) {
          this.startRecordHandle()
        }
      }, delay)
    },
    touchEndHandle() {
      if (!this.canRecordStart) return
      this.canRecordStart = false
      this.stopRecordHandle()
    },
  }
}
</script>

图像处理

获取图片信息

wx.getImageInfo

不管是CDN的图片还是本地选择的图片都需要先使用 getImageInfo 获取图片的基本信息

getImageInfo(img) {
  return new Promise((resolve, reject) => {
    wx.getImageInfo({
      src: img,
      success: res => { resolve(res) },
      fail: () => { reject('获取图片信息失败') }
    })
  })
}

选择图片

wx.chooseImage

让用户选择本地相册中或拍摄的图片,以选择单张图片为例:

const MB = 1024 * 1024
chooseSingleImage() {
  return new Promise((resolve, reject) => {
    wx.chooseImage({
      count: 1, // 默认9,为1获取单张图片
      sizeType: ['original', 'compressed'], // 指定是原图还是压缩图,默认二者都有
      sourceType: ['album', 'camera'], // 指定来源是相册还是相机,默认二者都有
      success: res => {
        let file = res.tempFiles[0]
        // 可以对所选图片尺寸或其他属性做一些限制
        // let { size } = file
        // if (size > 20 * MB) { reject('图片大小应小于20MB') }
        resolve(file)
      },
      fail: () => { reject('图片选取失败') }
    })
  })
}

读取图片

wx.getFileSystemManager()

使用小程序的FS相关API读取文件内容

readFileInBase64(filePath) {
  return new Promise((resolve, reject) => {
    if (wx.getFileSystemManager) {
      // 以base64编码读取图片
      wx.getFileSystemManager().readFile({
        filePath: filePath,
        encoding: 'base64',
        success: res => { resolve(res) },
        file: () => { reject('读取文件失败') }
      })
    } else {
      // 兼容处理,若不支持则提示更新
      wx.showModal({
        title: '提示',
        showCancel: false,
        content:
          '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
      })
    }
  })
}

Canvas绘制图像

小程序中使用CanvasContext API与H5的?#38382;?#22522;本相同。需要注意的是,在小程序中绘制canvas时尺寸的单位是 px ,而不是响应式的 rpx 。

需要注意的是从基础库 1.9.90 开始 CanvasContext 的API变化了很多,在使用时需要注意兼容性,比如下面两个函数:

export const drawPoint = (ctx, x, y) => {
  let pointColor = '#2ba5ff'
  ctx.beginPath()
  ctx.arc(x, y, 1, 0, Math.PI * 2, true)
  ctx.closePath()
  // 兼容画布填充色方法
  if (ctx.fillStyle) {
    // 1.9.90+
    ctx.fillStyle = pointColor
  } else {
    ctx.setFillStyle(pointColor)
  }
  ctx.fill()
}

export const drawRect = (ctx, x, y, width, height) => {
  let marginColor = '#ff0000'
  // 兼容笔触色彩方法
  if (ctx.strokeStyle) {
    // 1.9.90+
    ctx.strokeStyle = marginColor
  } else {
    ctx.setStrokeStyle(marginColor)
  }
  ctx.lineWidth = 1
  ctx.strokeRect(x, y, width, height)
}

mpvue

分包及分包预加载

mpvue-loader: ^1.1.2

直接在 app.json ?#20449;?#32622; subPackages 即可:

{
  ...
  "subPackages": [
    {
      "root": "pages/module-bob/",
      "pages": ["subpage-a/main", "subpage-b/main", "subpage-c/main"]
    },
    {
      "root": "pages/module-alice/",
      "pages": ["subpage-d/main", "subpage-e/main", "subpage-f/main"]
    }
  ],
  "preloadRule": {
    "pages/index/main": {
      "network": "wifi",
      "packages": ["pages/module-bob"]
    }
  }
  ...
}

其中 preloadRule 为预加载配置,上面的设置意为进入index页面时当为wifi网络时预加载module-bob子包。

使用globalData全局变量

在小程序中将自带的[ globalData ]()?#20197;?#21040;vue的原型方法上。

在src中的 main.js 最后添加如下代码:

import Vue from 'vue'
import App from './App'
...
const app = new Vue(App)
app.$mount()
Vue.prototype.$globalData = getApp().globalData // 添加该行

然后就可以在其他页面使用该命令操作全局变量了

// page A
this.$globalData.userInfo = {name: 'yrq110'}
// page B
console.log(this.$globalData.userInfo)
// page C
this.$globalData.userInfo.name: 'yrq110'

注意,在子页面中使用globalData时,将变量?#25345;?#30340;操作放在data中是无效的,如下:

export default {
  data() {
    // 无效
    // isIPX: this.$globalData.isIPX
  },
  computed: {
    isIPX() {
      // 有效
      return this.$globalData.isIPX
    }
  },
}

SVG图标组件的默认尺寸与预设尺寸

在图标组件中加载svg时使用父标签上的尺寸作为默认尺寸,并在传入特定props?#38382;?#26102;使用预设尺寸。

业务?#20449;?#21040;了这个问题,使用如下的方法进行了解决:在image组件的load?#24405;?#22788;理器中将加载的原始尺寸绑定到style上。

实现了: 1. 默认使用svg标签自带尺寸 2. 当传入size属性则使用预设尺寸

<template>
  <image
    ...
    @load="loadHandle"
    :style="{ width: !size ? iconWidth + 'rpx' : '100%', height: !size ? iconHeight + 'rpx' : '100%'}"
    ...
  />
</template>

<script>
export default {
  ...
  data() {
    return {
      iconWidth: 0,
      iconHeight: 0,
      loaded: false // 是否加载完毕
    }
  },
  props: {
    ...
    size: String
  },
  computed: {
    ...
    getSizeClass() {
      let { size } = this
      return size || ''
    },
    setSizeStyle() {
      if (!this.loaded || this.size) return {}
      return {
        width: this.iconWidth + 'rpx',
        height: this.iconHeight + 'rpx'
      }
    }
  },
  methods: {
    loadHandle(e) {
      this.loaded = true
      // 使用加载后的默认尺寸
      const { detail } = e.mp
      this.iconWidth = detail.width * 2
      this.iconHeight = detail.height * 2
    }
  }
  ...
}
</script>

解决无法在组件上绑定class的trick

将keyword作为prop属?#28304;?#20837;组件并通过Computed属性绑定到class上,这样在外部引用时就可以根据keyword设置自定义的样式了。

组件中的关键代码如下:

<template>
  <div :class="customClass">
    <slot></slot>
  </div>
</template>

<script>
export default {
  ...
  props: {
    type: String,
    ...
  },
  computed: {
    customClass() {
      let type = this.type || ''
      return type
    }
  }
  ...
}
</script>

在外部引用时就可以使用自定义class来在外部使用样式了:

<template>
  ...
  <g-button type="custom-button"></g-button>
  ...
</template>
...
<style lang="scss">
...
.custom-button {
  .text {
    margin-left: 10px;
  }
...
}
</style>
鲜花
鲜花
鸡蛋
鸡蛋
分享至 : QQ空间
收藏
原作者: Я?1I0 来自: 推酷
新时时彩软件