基于uni-app跨端框架开发IM项目实践总结(一)H5&微信小程序

160 阅读3分钟

前言

接到一个需求,寄生在APP中的h5开发的IM模块,需要实现微信小程序版本的同等功能。首先想到的是借用跨端框架,以最低成本实现现有代码往跨端框架中迁移,借用跨端框架的多端编译能力,实现一套代码同时编译到小程序和H5。

技术方案选型

目前,各大框架趋于稳定,RN、flutter、Taro、uni-app 也是目前最活跃的跨端工具,这里选择了uni-app,原因有以下几点:1)uni-app站队vue,需要迁移的代码也是vue技术栈;2)uni-app至2018开源至今,已拥900万开发者(官方文档数据),且归属在国内的移动开发领域有着广泛的影响力的于DCloud团队,生态丰富,开发文档友好;3)uni-app提供的条件编译能力能较好的解决不同端的环境差异问题,实现了APP、各类小程序、快应用的跨端效果,一套代码编到十几个平台,为以后业务扩展到其他平台也提供了支持。

技术栈:UniApp + Vite5 + Vue3 + Typescript + pinia

gitHub:github.com/simpleKeepe…

效果展示

以下视频非实际项目效果图,仅是调用期间对聊天主要功能的实践,但其主要能力(收发消息、下拉查看更多、消息回滚定位、发送图片、视频以及播放等等)都已正常实现,且无性能问题。

ezgif-3-1f73fefd16.gif

踩过的几个坑

  1. 下拉列表应用内置组件scroll-view,代码如下:
   <scroll-view
      :scroll-into-view="uniItemId"
      scroll-y="true"
      refresher-enabled
      class="scroll-Y"
      ref="myScrollView"
      :refresher-threshold="100"
      :scroll-with-animation="true"
      :refresher-triggered="triggered"
      @refresherrefresh="refresherpulling"
      @refresherpulling="onPulling"
      @refresherabort="onAbort"
    >
 //  中间为会话区各种格式的消息
    </scroll-view>
    
    // 自定义下拉刷新控件被下拉
function onPulling(e) {
  console.log('onpulling', e);
  if (e.detail.deltaY < 0) return; // 防止上滑页面也触发下拉
  triggered.value = true;
}
// 自定义下拉刷新被复位
function onRestore() {
  triggered.value = 'restore'; // 需要重置
  console.log('onRestore');
}
// 自定义下拉刷新被中止
function onAbort() {
  console.error('onAbort');
}
function refresherpulling() {
  if (_freshing) return;
  _freshing = true;
  setTimeout(() => {
    triggered.value = false;
    _freshing = false;
  }, 500);
  const Len = 5;
  for (let i = Len; i > 0; i--) {
    chatList.value.unshift({
      text: '第' + (chatList.value.length + Len - i) + '条下拉回复数据',
      avatarImg: '../../static/imgs/me-default.png',
      msgType: 1,
      msgSender: 1,
    });
    chatList.value.unshift({
      text: '第' + (chatList.value.length + Len - i) + '条下拉发送数据',
      avatarImg: '../../static/imgs/me-visitor.png',
      msgType: 1,
      msgSender: 0,
    });
  }
  // 定位前,先把原锚点清除,再重新设置锚点,否则第一次定位后,滚动滚动条,无法定位到锚点位置
  uniItemId.value = null;
  setTimeout(() => {
    uniItemId.value = `chatItem_${2 * Len - 2}`;
  }, 500);
}
  1. 应用scroll-into-view属性进行描点定位时,绑定的响应式数据在变更前先把原锚点清除,再重新设置锚点,否则第一次定位后,滚动滚动条,无法定位到锚点位置;
  2. :refresher-triggered="triggered"中,这个属性要随着下拉树下的过程变更状态,否则会导致下拉的loading状态一直不消失;
  3. :refresher-triggered="triggered"中triggered的初始值要设置为false,const triggered = ref<Boolean | string>(false);否则在小程序中初始化页面就会触发下拉刷新。
  1. 发送图片消息时,小程序和H5中存在差异,需要使用条件编译
    <view class="button-con" @click="chooseImage">
        <uni-icons type="image" size="30"></uni-icons>
        <text class="text">相片</text></view
      >
      
          // 发送图片、视频
    chooseImage() {
      const f = this;
      // #ifdef H5
      uni.chooseImage({
        count: 1, //默认9
        sizeType: ['original'], //可以指定是原图还是压缩图,默认二者都有
        sourceType: ['album'], //从相册选择
        success: function (res) {
          console.log(JSON.stringify(res.tempFilePaths));
          f.$emit('sendMeidaMsg', res.tempFilePaths[0], 2);
        },
      });
      //  #endif
      // #ifdef MP-WEIXIN
      uni.chooseMedia({
        count: 1,
        mediaType: ['image'],
        sourceType: ['album', 'camera'],
        maxDuration: 30,
        camera: 'back',
        success(res) {
          console.log(res.tempFiles);
          f.$emit('sendMeidaMsg', res.tempFiles[0].tempFilePath, 2);
        },
      });
      //  #endif
    },
  1. 样式在不同平台的差异性 例如当设置了box-sizing: border-box时,在小程序中设置宽度依旧要考虑padding的距离,h5中某些父元素可以根据子元素自动把高度撑开,但是在小程序中需要设置具体高度等等。毕竟小程序独立的运行时环境和浏览器的运行时环境有差异,这些不兼容也在所难免。
/* #ifdef MP-ALIPAY || MP-WEIXIN */
.popup-content {
  width: 360px;
  height: 106px;
}
  /* #endif */
::v-deep .uni-row {
  position: absolute !important;
  bottom: 10px;
  width: 100%;
  /* #ifdef MP-WEIXIN */
  width: calc(100% - 28rpx);
  /* #endif */
  background: #f6f6f6;
  padding: 8rpx 16rpx 8rpx 12rpx;
  display: flex;
  align-items: center;
  z-index: 9;
  .img-con {
    .img {
      width: 26rpx;
      height: 26rpx;
    }
  }
}

结束语

在迁移IM模块原始代码到uni-app框架的过程中,确实遇到了一些问题,但总体来说,解决的并不算艰难。编译生成的小程序包在微信开发者工具中的调试也能正常定位,加上得益于官方文档的友好,广大开发者经验输出,原来的H5代码迁移到uni-app,并编译成H5和小程序2套代理,总体算是顺利,相比于重新开发一套小程序代码,大大的节省了开发和维护成本。