微信小程序开发知识记录

129 阅读4分钟

小程序性能优化

  • 分包
    合理的分包可以明显的加快第一次打开小程序的速度, 减小主包的代码体积

    • 在app.json 中定义subPackages。
    • 配合 preloadRule (预加载分包的规则), 可以做到无缝打开分包页面
    • 配合 wx.onLazyLoadError , 监听分包下载失败,从而导致分包页面白屏
  • 组件懒加载

    • 在app.json 中定义"lazyCodeLoading": "requiredComponents"
    • 在具体的页面json 文件中, 定义到componentPlaceholder 字段下的组件均会进行懒加载。
    • 注意: 懒加载会改变组件生命周期的表现。 例如: 一个组件在未懒加载时, 组件的show 方法会早于页面的onShow 方法, 使用了懒加载后, show方法可能不会执行。
  • 内存占用优化:

    • 控制页面栈的数量

      • 在页面栈数量较多时,可以使用wx.reLaunch、wx.switchTab、wx.redirectTo来优化页面栈数量。例如: 在一次完整的提交流程后, 跳转到成功页面, 在点击返回按钮时,直接使用relaunch 来进入首页。
    • 全局变量控制

      • 尽量少使用globalData
      • 如果有必要,请及时清除,并且注意非常规流程是否清除
    • 优化内存泄漏

      • 参考这篇文章中的第5条来查看代码中是否存在常见的内存泄漏问题
      • 可以通过memory面板来定位是否会发生内存泄漏 参考文章
    • 定义在page方法外的变量注意内存占用(防止占用内存较大,而且不会被GC)

    •    // 定义在这里的对象不会被GC
         const customData = {}
         
         Page({
         })
      
  • setData 优化。 参考文章

    • 多次setData操作合并。 因为多次调用setData默认是不会进行合并的, 会设计到多次和wxml通信过程,相对较耗时。
    • setData 中data变量尽量只覆盖wxml需要的变量, 非渲染使用的变量可以直接挂载到this中的某个变量上。
    • 在自定义组件中, 可以使用pureDataPattern: /^_/ 来优化data 大小
    • 在优化老代码时, 可以通过开发者工具中体验评分功能(路径: 详情 --> 性能质量 --> 体验评分)来具体定位哪些data 字段是不需要的。
  • wxml 优化

    • 减少wxml 的大小, 可以优化内存占用, 所以尽量使用wx:if 来优化不展示的节点或者自定义组件。
  • 图片资源优化

    • 图片均通过cdn来引入
    • 图片尽量压缩
    • 懒加载图片资源:在image 标签中使用lazy-load来控制
  • 音视频资源优化

    • 音视频资源通过cdn来引入
    • 进行懒加载控制,用户没有点击播放时,尽量控制资源的加载。主要是通过控制src 属性, 存在src属性就会加载资源。
    • 当存在音视频资源的列表时, 尽量共用一个context上下文, 通过切换src 来实现音视频资源的切换。
  • 有长列表需求可以引入虚拟列表

    • 如果不想额外引入插件, 可以通过createIntersectionObserver 来模拟一个虚拟列表的控制

小程序音频相关

  • 针对iphone 设备的静音播放
    wx.setInnerAudioOption({
      obeyMuteSwitch: false,
      mixWithOther: false
    })
  • 不要再page函数外面去创建音频上下文,尽量直接在onLoad里面生成一个挂载到this对象上面的上下文
// 这里定义的上下文对象是不会GC的
const innerAudioContext = wx.createInnerAudioContext({
  useWebAudioImplement: false
})
page({
  global: {}
  onLoad() {
   // 这样定义页面清除后,会清空
    this.global.innerAudioContext = wx.createInnerAudioContext({
      useWebAudioImplement: false
    })
  }
})
  • 尽量使用onCanPlay来监听是否可以播放, 不要直接innerAudioContext.play。 这里只针对多个音频,切换了src后的播放, 一个音频就直接play就行
    if (this.global.innerAudioContext.src !== src) {
        const contextPlay = () => {
          this.global.innerAudioContext.play()
          this.global.innerAudioContext.offCanplay(contextPlay)
        }
        // 需要播放的时候这样处理
        this.global.innerAudioContext.onCanplay(contextPlay)
    } else {
        this.global.innerAudioContext.play()
    }
  • onUnload 时清除监听器
this.global.innerAudioContext.offEnded()
this.global.innerAudioContext.offError()
this.global.innerAudioContext.destroy()

小程序视频相关

  • 视频无法全屏(现象: 点击播放只有声音没有全屏图像)

    • 主要出现在多视频,同时共用同一个视频context的情况下.
    • <video
        id="video"
        class="video"
        src="{{videoSrc}}"
        bindfullscreenchange="fullscreenchange"
        bindloadedmetadata="handelLoadedMetaData"
      ></video>
      
    •   playVideo(e) {
          const { url } = e.detail
          const curVideoSrc = url
          if (this.data.videoSrc === curVideoSrc) {
            this.videoCtx.requestFullScreen({
              direction: 0
            })
            this.videoCtx.play()
            return
          }
          if (this.data.videoSrc && this.videoCtx) {
            this.videoCtx.stop() // 停止正在播放的视频
          }
          this.videoCtx = wx.createVideoContext('video')
          this.setData({
            videoSrc: curVideoSrc
          })
        },
        fullscreenchange(e) {
          if (!e.detail.fullScreen) {
            this.videoCtx.pause()
          }
        },
        handelLoadedMetaData(e) {
          // 元数据加载完成后, 调用全屏和播放
          this.videoCtx.requestFullScreen({
            direction: 0
          })
          this.videoCtx.play()
        },
      
  • 多视频资源怎么优化内存占用

    • 尽量在一个page中共用一个video 上下文。 同时在视频需要播放的时候再加载视频资源(可以通过控制video 的src是否有值来实现)
  • 视频的context 在组件中无法使用

    • 需要绑定this, wx.createVideoContext('video', this)

小程序状态管理

总体架构: 通过发布订阅模式来建立一个数据中心,然后页面与数据中心建立绑定关系, 通过相应的方法获取数据信息或者设置数据信息。

代码片段