小程序的发展,从一开始的 template 到现在的组件化开发,以及 uni-appTaro 等框架的兴起。也该去爬爬坑,爬坑的需求来源于之前的一次录音评测项目,用到了录音接口以及websocket能力。

框架选择

因为最近一直在用 React 做web开发,对于原生的微信小程序的 API,不是很喜欢回调函数式的写法,所以目标就瞄准了 Taro。下载、安装、初始化在文档中都描述的非常清晰~

使用的一些注意

由于不是使用的原生的微信提供的框架来写,所以有一些地方还是不太相同的。

  • class 与 hooks 写法的不同

在 Taro 的官方文档中,大多数的例子都是用的 class 语法。在 v1.3.0 版本之后支持了 hooks 写法,且基础的 hooks 和 react 保持使用上的相同,并且增加了小程序独有的一些 hooks。主要介绍传送门

  • 引入三方UI库

其实 Taro 官方有一个 Taro-UI 的 UI 组件库,但是通过 github 的 commit 记录看到已经很久没有更新了,所以希望引入别的三方 UI 组件库。比如: Vant WeappLin UI

由于使用过的是三方的 UI 库,在 Taro 的项目打包编译出来的代码里面是没有 package.json 这个 npm 构建需要的文件的,所以引入组件的方式需要变更,不能按照微信的原生引入三方组件的方式,需要自己单独下载一份组件代码,放到项目中引用。

// 在 components 文件夹中放置打包编译好的 UI 组件
|-- components
|--|-- vant-ui
|--|--|-- button
|--|--|-- card
|--|--|-- checkbox
|--|--|-- dialog
...

// 在组件或者页面中引入
const Page = () => {
  return (
    <vant-button>按钮</vant-button>
  );
}

Page.config = {
  usingComponents: {
    'vant-button': 'path/to/components/vant-ui/button'
  },
};

export default Page;
  • redux 的使用

在官方初始化的模板项目里面,有给到 redux 的使用方式,是通过装饰器 + class 来实现的。但是更换 hooks 之后,就不能使用了。所以需要更换为在 web 开发中 react-redux 的使用方式。

import { connect } from '@tarojs/redux';
import * as actionCreators from 'path/to/actionCreators';

const Page = ({
  stateKey,
}) => {
  return (
    // jsx
  );
}

const mapStateToProps = (state) => {
  return {
    stateKey: state.stateKey,
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    dispatchHandler: (arguments) => {
      dispatch(actionCreators.actionFn(arguments));
    }
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(Test);

当然,以上方式看上去比较繁琐,也可以使用官方提供的 redux-hooks 进行操作。详见

  • 微信小程序官方录音API的使用

录音的能力,在小程序中不需要显示的去获取用户的权限,只是会在用户首次触发了录音事件的时候,给用户提示是否允许获取麦克风的权限。

  1. 如果要实时的获取到用户的录音数据,需要调用 RecorderManager 录音管理器的 onFrameRecorded 方法,API 在录制到指定帧大小的时候触发。

但是在实际使用过程中,发现了在微信开发者工具中始终不会主动触发此事件,真机调试则可以触发。且谨记只有 MP3 格式设置了 frameSize 才可以触发(2020年3月)。

  1. 如果需要录音结束的时候获取到录音的文件,进行处理发送接口请求结果。则需要在 onStop 的回调中,获取录音文件的临时路径。
const RecorderManager = Taro.getRecorderManager();
const FileSystemManager = Taro.getFileSystemManager();

RecorderManager.onStop(async ({ tempFilePath }) => {
  FileSystemManager.readFile({
    filePath: tempFilePath,
    encoding: 'base64',
    // 读取到录音文件 的 base64 数据
    success: (data) => {
      // data 即为数据
    },
  );
})

正常情况下这段代码应该是无懈可击的,但是在实际的开发调试过程中,发现通过微信开发者工具进行录音最终产出的音频文件是无法使用的,尝试通过音频播放 API 进行播放也会失败。后查询资料,在微信官方开发者社区,看到微信开发者工具返回的文件格式并不是录音初始时设定的格式,所以无法使用。因此此接口的使用只能放置到真机调试中去。

  • websocket 的调试

在录音的过程中,实时触发onFrameRecorded并且传递给后端进行分析。所以使用了 websocket 进行出具传递。

然而在实际操作过程中,由于录音的 onFrameRecorded 方法必须使用真机调试模式才能有回调结果,但是在真机调试过程中,发现真机调试模式 network 中,websocket 并不是一个 ws 请求,而是归类在 xhr 中,但是发出请求之后的状态码确实是 101 ,但是却无法查看每一次前后端通信的具体内容。其实在官方的社区论坛很早有开发者提出这个问题,但没有具体的回复答案,详见

经过一系列的调试之后,发现这个情况只是一个展示上的错误,实际上请求与回复是存在的,但是由于笔者测试的时候 websocket 是用的本地的服务(ip + port)进行测试的,在开发者工具中是完好的,只要一打开真机调试模式就莫名其妙的接收不到消息,导致之后的操作代码都没有执行。

因为微信提供了 不校验合法域名…HTTPS证书 这个选项,在勾选上之后出现的以上问题,所以笔者就没有往 HTTPS 请求的问题上面考虑,但是事实确很残酷,在经历了多次debugger之后仍然不行,最终更换了 https + 域名 之后,以上的问题就不存在了。

综上: 在真机调试的时候必须使用https + 域名的模式去连接,不然就会出现没有任何报错,但是却不接收消息。与安卓调试 websocket 的情况一致,应该是被拦截掉了,http服务以及ws服务都存在相同的问题。

  • 云开发

小程序的云开发在一定程度上弱化了后端的作用,让前端开发者可以直接使用 Js 操作数据库提供接口能力~

在尝试是使用云开发的时候,调试不太顺畅,所以做一个记录。

云开发主要是编写云函数调用API能力或者其他云函数能力,在调试的时候有几种模式:1、本地调试 2、真机调试 3、云端调试。在云端调试的时候,主要是编写调用模板,触发函数体,基本是由微信开发者工具直接完成。

  1. 本地调试

    本地调试需要选择云函数文件夹,右击选择菜单中的 开启云函数本地调试,之后再弹出的操作框中,选择需要调试的云函数,选择右边的 开启本地调试 选项。之后就可以直接在开发者工具中调试云函数。

  2. 真机调试

    真机调试需要连接手机,并且云函数需要部署到云服务上去。选择具体的云函数文件夹,右击选择菜单中的 上传并部署 (两个选项都可,一个不行更改另一个)。之后在手机端就可以进行调试。但是需要注意的是,当你改变代码的时候,并不会实时上传部署,所以要更改代码之后手动再次 上传并部署

当然在进行调用云函数之前,一定要初始化云函数的调用功能,详见,环境ID是在微信开发者工具->云开发->设置->环境设置中,谨记是ID不是名称~!。

总结

以上是本次在体验 Taro 开发小程序的过程中,目前所遇到的一些问题,做一个笔录。后续如果还有会继续更新~


# JavaScript