Skip to content

跨平台开发 Taro

[TOC]

入门

概述

认识 Taro 框架

什么是 Taro?

  • Taro 是由京东 凹凸实验室 打造的一个开放式跨端、跨框架解决方案,并于 2018 年 6 月 7 日正式开源。

  • Taro 支持使用 React/Vue/Preact等框架来开发 微信/ 京东/ 百度/ 支付宝/ 字节跳动/ QQ等小程序 / H5 / RN 等应用。

Taro 的版本史

  • Taro 1.x / 2.x 版的文档,现已不再积极维护。

  • 2021 年 3 月,Taro 3.1版本正式发布,主要改动是打造开放式架构,支持以插件的形式编译到任意小程序平台。

  • 2021 年 4 月,Taro 3.2 版本正式发布,新增了对 ReactNative 的支持,主要是由 58 同城团队主导。

  • 2021 年 4 月,Taro 3.3 alpha 发布,主要改动是支持使用 HTML 标签进行开发。

  • 2022 年 1 月,Taro 3.4版本正式发布,主要改动是支持使用 PreactVue3.2 进行开发。

  • 目前 Taro 团队的迭代重心在于 Taro 3,Taro 1 / 2 只会对重大问题进行修复,不会新增新特性。

Taro 的特点

image-20240731120410322

多端支持

  • Taro 3 可以支持转换到 H5、ReactNative 以及任意小程序平台(重心是小程序端)。

  • 目前官方支持转换的平台如下:

    • H5、ReactNative、微信小程序、京东小程序、百度小程序、支付宝小程序、字节跳动小程序

    • QQ 小程序、钉钉小程序、企业微信小程序、支付宝小程序等

多框架支持

  • 在 Taro 3 中可以使用完整的 React / Vue2 / Vue3 / Nervjs / Preact 开发体验

Taro vs uni-app

  • 跨端支持度

    image-20240731120441784

  • 社区活跃度

    image-20240731120457862

  • 资料完善度

    • Taro: 官方文档较完整,但不是很丰富,资料一般
    • uni-app:官方文档和各种专题内容很丰富,资料齐全
  • 工具和周边生态

    • Taro:官方的 Taro UI,只支持小程序和 H5( 不支持 RN ),截至到 2019 年 10 月 28 日, Taro 只有 64 个插件。

    • uni-app:官方的 uni-ui 支持多端、周边模板丰富、完善的插件市场,截至到 2019 年 10 月 28 日,有 850 个插件。

  • Taro 和 uni-app 如何选择?

    • 如需要跨平台,并且应用不是很复杂,可选 Taro 和 uni-app。

    • 如熟悉 Vue 可优先选择 uni-app; 如熟悉 React 推荐使用 Taro。

    • uni-app 在资料、生态、工具、开发效率、跨端数会比 Taro 略胜一筹。

    • 当然 Taro 也有独特的优势,如:用 React 开发非常的灵活。

Taro 架构图设计图

Taro 当前的架构主要分为:编译时运行时

其中编译时主要是将 Taro 代码通过 Babel[11] 转换成 小程序的代码,如:JS、WXML、WXSS、JSON。

运行时主要是进行一些:生命周期、事件、data 等部分的处理和对接,以保证和宿主平台数据的一致性。

image-20240731120622475

编辑器选择

推荐使用 VSCodeWebStorm

当你使用 VSCode 时,推荐安装 ESLint 插件

  • 如果你使用 TypeScript,别忘了配置 eslint.probe 参数。

  • 如果使用 Vue,推荐安装 Vetur 或 Volar 插件,目前(2024-8-13)已被 Vue - Official代替。

如果你愿意花钱又懒得折腾可以选择 WebStorm,基本不需要配置。

不管使用 VSCode 还是 WebStrom,安装了上述插件之后使用 Taro 都实现自动补全和代码实时检查(linting)的功能。

初体验

安装

node 环境: Taro 项目基于 node,请确保已具备较新的 node 环境(>=16.20.0

安装:

1、使用 npm 或者 yarn 全局安装 @tarojs/cli,或者直接使用 npx:

sh
pnpm i @tarojs/cli -g # pnpm

npm i @tarojs/cli -g # npm

yarn global add @tarojs/cli # yarn

2、查看 Taro CLI 工具版本

sh
npm info @tarojs/cli

image-20240813105210995

3、查看@tarojs/cli 所有发行版本

sh
pnpm view @tarojs/cli versions

image-20240813105128343

项目初始化

1、方式一:使用命令创建模板项目

sh
taro init myApp

image-20240813110304837

2、方式二:npm 5.2+ 也可在不全局安装的情况下使用 npx 创建模板项目

sh
npx @tarojs/cli init myApp

3、安装依赖

sh
pnpm i

注意:

  • 开发支付宝小程序时,Webpack4不支持使用 React18

  • 受小程序环境限制,诸如新 SSR Suspense 等特性将不能在小程序中使用

  • RN不支持 React18,需要等待 RN 官方输出支持方案。

  • 为了顺利地用 Taro 来开发 App,我们强烈地建议您,先对 React Native 开发进行学习。

编译运行

使用 Taro 的 build 命令可以把 Taro 代码编译成不同端的代码,然后在对应的开发工具中查看效果。

Taro 编译分为 devbuild 模式:

  • dev 模式(增加 --watch 参数) 将会监听文件修改。

    sh
    # yarn - 启动
    yarn dev:h5
    yarn dev:weapp
    
    # pnpm - 启动
    pnpm run dev:h5
    pnpm run dev:weapp

    注意: 启动小程序时需要手动打开项目目录的/dist/文件夹下的项目

  • build 模式(去掉 --watch 参数) 将不会监听文件修改,并会对代码进行压缩打包。

    sh
    # yarn - 打包
    yarn build:h5
    yarn build:weapp
    
    # pnpm - 打包
    pnpm run build:h5
    pnpm run build:weapp
  • dev 模式生成的文件较大,设置环境变量 NODE_ENVproduction 可以开启压缩,方便预览,但编译速度会下降。

image-20240731120840605

目录结构

image-20240731120850069

Taro+React 开发规范

为了实现多端兼容,综合考虑编译速度、运行性能等因素,Taro 可以约定了如下开发规范:

  • 页面文件遵循 React 组件 JSX 规范

  • 组件标签 靠近小程序规范(但遵从大驼峰,并需导包),详见 Taro 组件规范

  • 接口能力(JS API)靠近微信小程序规范,但需将前缀 wx 替换为 Taro(需导包),详见Taro 接口规范

  • 数据绑定事件处理React 规范,同时补充了 App 及页面的生命周期

  • 为兼容多端运行,建议使用flex 布局进行开发,推荐使用 px 单位(750 设计稿)。

  • 在 React 中使用 Taro 内置组件前,必须从 @tarojs/components 进行引入。

  • 文档直接查看 Taro 的官网文档: https://docs.taro.zone/docs

配置文件

webpack 编译配置 config

编译配置存放于项目根目录下的 config 目录中,包含三个文件:

  • index.js:是通用配置

  • dev.js:是项目开发时的配置

  • prod.js:是项目生产时的配置

image-20240731120926724

常用配置项:

  • projectName : 项目名称

  • date : 项目创建时间

  • designWidth: 设计稿尺寸

  • sourceRoot : 项目源码目录

  • outputRoot: 项目产出目录

  • defineConstants: 定义全局的变量(DefinePlugin),需要如下写:VERSION: "'1.0.O'"

  • alias: 配置路径别名

  • h5.webpackChain: webpack 配置

  • h5.devServer :开发者服务配置

  • 更多的配置:https://docs.taro.zone/docs/config

全局配置 app.config.js

app.config.js 用来对小程序进行全局配置,配置项遵循微信小程序规范,类似微信小程序的 app.json,并对所有平台进行统一

image-20240731120955852

更多的配置:https://docs.taro.zone/docs/next/app-config

页面配置 .config.js

每一个小程序页面都可以使用 .config.js 文件来对本页面的窗口表现进行配置。

image-20240731121048858

页面中配置项在当前页面会覆盖全局配置 app.config.json 的 window 中相同的配置项。

image-20240731121056300

文件需要 export 一个默认对象,配置项遵循微信小程序规范,并且对所有平台进行统一。

更多页面配置:https://docs.taro.zone/docs/next/page-config

项目配置 project.x.json

为了适配不同的小程序, Taro 支持各个小程序平台添加各自项目配置文件。

  • 默认 project.config.json 配置只能用于微信小程序

project.config.json 常用配置

  • libVersion 小程序基础库版本

  • projectname 小程序项目名字

  • appid 小程序项目的 appid

  • setting 小程序项目编译配置

各类小程序平台均有自己的项目配置文件,例如:

image-20240731121109621

基础

内置组件

入口组件 app.js

每一个 Taro 应用都需要一个入口组件(如 React 组件)用来注册应用。入口文件默认是 /src/app.js

作用: 在入口 app.js 组件中我们可以:

  • 定义应用的生命周期

    • onLaunch()useEffect:在小程序环境中对应 app 的 onLaunch。
    • componentDidShow()useDidShow:在小程序环境中对应 app 的 onShow 。
    • componentDidHide()useDidHide:在小程序环境中对应 app 的 onHide 。
  • 定义全局数据

    • taroGlobalData
  • 定义全局样式

  • 定义应用的全局状态

    • Redux
    • Vuex
    • Pinia

一、定义应用的生命周期

image-20240813123818215

二、定义全局数据

1、在 app.js 中定义全局数据

image-20240813123559410

2、在页面中获取全局数据

image-20240813123957468

三、定义全局样式

app.scss中定义全局样式

image-20240813124346936

常用内置组件

  • View:视图容器。用于包裹各种元素内容(Taro3.3 以后支持使用 HTML 标签 进行开发)

  • Text:文本组件。用于包裹文本内容。

  • Button:按钮组件,多端主题色一样

  • Image:图片。支持 JPG、PNG、SVG、WEBP、GIF 等格式以及云文件 ID。

    • 默认宽高
      • H5:图片宽高
      • weapp:Image 组件的默认宽高
    • 支持import 导入URL网络图片。不支持路径写法(包括绝对路径,相对路径)
  • Scrollview:可滚动视图区域,用于区域滚动。

    • 使用竖向滚动时,需要给<scroll-view>一个固定高度,通过 css 设置 height

    • 使用横向滚动时,需要给<scroll-view>添加 white-space: nowrap;样式,子元素设置为行内块级元素。

    • 小程序中,请勿在 scroll-view 中使用 map、video 等原生组件,也不要使用 canvas、textarea 原生组件。

  • Swiper:滑块视图容器,一般作为 banner 轮播图,默认宽 100%,高 150px。

View / Text

image-20240813125031071

Button

image-20240813125410153

Image

image-20240813130605946

Scrollview

垂直滚动

image-20240813130755781

image-20240813130800018

水平滚动

image-20240813131012512

image-20240813130947552

Swiper

image-20240813131700121

样式

设计稿及尺寸单位(px)

Taro 默认以 750px 作为换算尺寸标准,如设计稿不是 750px 为标准需修改 designWidth

  • 比如:设计稿是 640px,则需修改 config/index.js 中 designWidth 为 640

    image-20240731121156211

在 Taro 中单位建议使用 px、 百分比 %,Taro 默认会对所有单位进行转换。

  • 在 Taro 中写尺寸按照 1:1 关系来写,即设计稿量长度 100px,那么尺寸就写 100px

    当转成微信小程序时尺寸为 100rpx,当转成 H5 时尺寸以 rem 为单位。

  • 如你希望部分 px 单位不被转换成 rpx 或 rem ,最简单做法就是在 px 单位中增加一个大写字母

JS 中行内样式的转换

  • 在编译时,Taro 会帮你对样式做尺寸转换操作

  • 但是如果是在 JS 中书写了行内样式,那么编译时就无法做替换了

  • 针对这种情况,Taro 提供了 API Taro.pxTransform() 来做运行时的尺寸转换。

    image-20240731121208054

示例:

image-20240813164539487

image-20240813164753165

CSS 编译时忽略

1、忽略单个属性: 当前忽略单个属性的最简单的方法,就是 px 单位使用大写字母。

image-20240731121218459

2、忽略样式文件: 对于头部包含注释 /* postcss-pxtransform disable */ 的文件,插件不予转换处理。

image-20240813165701470

3、忽略行内样式: 行内样式默认不会被转换,如果想要转换需要使用 Taro.pxTransform()

image-20240813170333716

全局和局部样式

全局样式

  • Taro 页面和普通组件导入的样式默认都是全局样式

  • 那在 Taro 中应该如何编写局部的样式呢?使用 CSS Modules 功能

局部样式

1、在 config/index.js 配置文件中启用 CSS Modules 的功能,改完后重新运行pnpm run dev

image-20240813171450729

image-20240813171513033

2、编写的样式文件需要加上 .module 关键字。如: index*.module*.scss

image-20240813172259576

3、然后在组件中导入该样式文件,即可以按照模块的方式使用了。

image-20240813172322189

image-20240813172236571

4、CSS Modules 中也支持编写全局样式

image-20240813172456555

背景图片

Taro 支持使用在 css 里设置背景图片,使用方式与普通 web 项目大体相同,但需要注意以下几点:

  • 支持 base64 格式图片,支持网络路径图片

使用本地背景图片需注意

  • 小程序不支持在 css 中使用本地文件,包括本地的背景图和字体文件。需以 base64 方式方可使用。

  • 为了方便开发,Taro 提供了直接在样式文件中引用本地资源的方式,其原理是通过 PostCSS 的 postcss-url插件将样式中本地资源引用转换成 Base64 格式,从而能正常加载。

    /config/index.js中的mini.url.config.maxSize: 2024,单位:KB,设置转化 base64 的最大尺寸限制:

    image-20240813173326643

  • 不建议使用太大的背景图,大图需挪到服务器上,从网络地址引用。

  • 本地背景图片的引用支持:相对路径绝对路径

    image-20240731121323115

字体图标

注意: 和 uni-app 语法一样

Taro 支持使用字体图标,使用方式与普通 web 项目相同:

第一步:先生成字体图标文件

第二步:app.scss 引入字体图标

image-20240731121401726

第三步:组件中使用自定义字体

image-20240813174340406

页面和传参

Page

创建页面方式:

1、命令行创建: 能够在当前项目的 pages 目录下快速生成新的页面文件,并填充基础代码,是一个提高开发效率的利器。

sh
# --name可以省略
Taro create --name [页面名称]

image-20240813175224634

2、手动创建页面: 在目录根目录下的 pages 目录下新建即可。

注意: 新建的页面,都需在 app.config.json 中的 pages 列表上配置。

image-20240813175440966

删除页面: 删除页面,需做两件工作

  • 删除页面对应的文件

  • 删除 app.config.json 中对应的配置

Tabbar

在 app.config.js 中配置 Tabbar

icon 路径支持绝对路径相对路径

image-20240731121417847

image-20240813175605769

页面路由

Taro 有两种页面路由跳转方式:使用 Navigator组件跳转、调用API跳转。

  • 组件:Navigator

  • 常用 API:navigate 、redirectTo、switchTab、navigateBack

image-20240731121436680

image-20240731121445819

页面通讯

在 Taro 中,常见页面通讯方式:

  • 方式一:url 查询字符串

  • 方式二:EventChannel(只支持小程序端)

  • 方式三:全局事件总线: Taro.eventCenter

  • 方式四:全局数据:taroGloabalData

  • 方式五:本地数据存储: Taro.setStorageSync(key, data) 等

  • 方式六:Redux 状态管理库

查询字符串-正向
  • 传递参数:?name=liujun&id=100

  • 获取参数:

    • onLoad 、 useLoad 生命周期获取路由参数

    • Taro.getCurrentInstance().router.params 获取路由参数。

1、传参:直接在 url 后面通过查询字符串的方式拼接

image-20240815101330273

2、接收:

  • 方式一:在onLoaduseLoad 生命周期中通过options.xxx获取 url 传递的参数

    image-20240815101419924

  • 方式二:通过Taro.getCurrentInstance().router.params获取 url 传递的参数

    image-20240815101829801

  • 方式三:通过 hooks 获取参数

    image-20240815120729380

EventChannel-正向

注意: 只支持小程序端

1、传参:在success回调中通过res.eventChannel.emmit(事件, 参数) 传递参数

image-20240815105925611

2、接收:在onLoad生命周期中通过this.$instance.page.getOpenerEventChannel()获取参数

注意: 在 uni-app 中是通过this.getOpenerEventChannel()获取eventChannel对象的。

image-20240815105816259

EventChannel-逆向

1、跳转到目标页

image-20240815110553894

2、在目标页点击返回按钮,跳转回来源页,并通过 eventChannel 携带参数

image-20240815110809670

image-20240815110749174

注意: 获取当前 page 的 eventChannel 的方法:

  • js
    // 方法一
    $instace = Taro.getCurrentInstance()
    const eventChannel = this.$instance.page.getOpenerEventChannel()
  • js
    // 方法二
    const pages = Taro.getCurrentPages()
    const page = pages[pages.length - 1]
    const eventChannel = page.getOpenerEventChannel()

3、在来源页,通过 navigateTo 的 envets 选项中监听发射过来的事件,并获取传递的参数

image-20240815111642018

事件总线-逆向

为了支持跨组件、跨页面之间的通信,Taro 提供了全局事件总线:Taro.eventCenter

  • Taro.eventCenter.trigger()(eventName, args),触发一个事件
    • eventNamestring默认:,事件名称
    • argsany默认:,事件参数
  • Taro.eventCenter.on()(eventName, cb),监听一个事件
    • eventNamestring默认:,事件名称
    • cb(args => void)默认:,事件监听函数
      • args any默认:,触发事件参数
  • Taro.eventCenter.off()(eventName, cb?),取消监听事件。如果没有提供参数,则移除所有的事件监听器
    • eventNamestring默认:,事件名称
    • cb?(args => void)默认:,事件监听函数
      • args any默认:,触发事件参数

注意:

  • 需先监听,再触发事件,比如:你在 A 界面触发,然后跳转到 B 页面后才监听是不行的。

  • 通常 on 和 off 是同时使用,可以避免多次重复监听

  • 适合页面返回传递参数、适合跨组件通讯不适合界面跳转传递参数。即适合逆向传参,不适合正向传参

1、跳转到目标页

image-20240815111841671

2、在目标页触发事件,并传递参数

image-20240815112335129

image-20240815112358248

3、在来源页监听事件,并获取传递的参数

image-20240815112545336

生命周期

Page 生命周期

Taro 页面组件除了支持 React 组件生命周期 方法外,还根据小程序的标准,额外支持以下页面生命周期

  • onLoad()(options),小程序:onLoad(),监听页面加载,该钩子被调用时,响应式数据、计算属性、方法、侦听器、props、slots 已设置完成。
    • optionsobject,上个页面传递的数据。
    • 注意: 通过访问 options 参数或调用 getCurrentInstance().router,可以访问到页面路由参数。
  • onUnload ()(),小程序:onUnload(),监听页面卸载。
    • 注意: 建议使用 React 的 componentWillUnmount 生命周期处理页面卸载时的逻辑。
  • onReady()(),小程序:onReady(),监听页面初次渲染完成,此时组件已挂载完成,DOM 树($el)已可用,注意如果渲染速度快,会在页面进入动画完成前触发。
    • 注意: 可以使用 createCanvasContext 或 createSelectorQuery 等 API 访问小程序渲染层 DOM 节点
  • componentDidShow()(),小程序:onShow(),监听页面显示,页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面。
  • componentDidHide ()(),小程序:onHide(),监听页面隐藏。
  • onPullDownRefresh():,监听用户下拉动作,一般用于下拉刷新。
    • 启用下拉刷新: 设置index.config.js中的definePageConfig.enablePulldownRefresh: true
    • 关闭下拉刷新: Taro.stopPullDownRefresh()
  • onReachBottom():``,页面滚动到底部的事件(不是 scroll-view 滚到底),常用于下拉下一页数据。

更多:https://docs.taro.zone/docs/react-page/#生命周期方法

image-20240731121503910

Hooks 生命周期

Taro 使用 Hooks 很简单。Taro 专有 Hooks,例如 usePageScroll, useReachBottom,需从 @tarojs/taro 中引入

React 框架自己的 Hooks ,例如 useEffect, useState,从对应的框架引入。

更多的 Hooks 可查看官网: https://docs.taro.zone/docs/hooks

image-20240731121513734

image-20240731121520482

image-20240815120438908

常用 API

网络请求

Taro.request(OBJECT) 发起网络请求

  • 在各个小程序平台运行时,网络相关的 API 在使用前需要配置合法域名(域名白名单)。

  • 微信小程序开发工具在开发阶段可以配置:不校验合法域名。

  • header 中的 content-type 属性的默认值为:application/json

image-20240731121546537

image-20240815121507263

封装请求

参考:uni-app 的封装

数据缓存

  • 同步存取数据的方法:

  • Taro.setStorageSync()(key, data),将数据存储在本地缓存中指定的 key 中。会覆盖掉原来该 key 对应的内容

    • 参数:key, data
    • keystring,本地缓存中指定的 key
    • dataany,需要存储的内容。只支持原生类型、Date、及能够通过JSON.stringify序列化的对象
  • Taro.getStorageSync()(key),从本地缓存中同步获取指定 key 的内容

    • 参数:key
    • keystring,本地缓存中指定的 key
    • 返回值:any
    • anyany,key 对应的内容
  • Taro.removeStorageSync()(key),从本地缓存中移除指定 key。

    • 参数:key
    • keystring,本地缓存中指定的 key
  • Taro.clearStorageSync()(),清理本地数据缓存。

  • 异步存储数据的方法:

  • Taro.setStorage()(object),将数据存储在本地缓存中指定的 key 中。会覆盖掉原来该 key 对应的内容

    • 参数:object
    • keystring,本地缓存中指定的 key
    • dataany,需要存储的内容。只支持原生类型、Date、及能够通过JSON.stringify序列化的对象
    • successfunction(res),接口调用成功的回调函数
    • failfunction(err),接口调用失败的回调函数
    • completefunction(res),接口调用结束的回调函数(调用成功、失败都会执行)
  • Taro.getStorage()(object),从本地缓存中异步获取指定 key 的内容

    • 参数:object
    • keystring,本地缓存中指定的 key
    • successfunction(res),接口调用成功的回调函数
    • failfunction(err),接口调用失败的回调函数
    • completefunction(res),接口调用结束的回调函数(调用成功、失败都会执行)
  • Taro.removeStorage()(object),从本地缓存中移除指定 key。

    • 参数:object
    • keystring,本地缓存中指定的 key
    • successfunction(res),接口调用成功的回调函数
    • failfunction(err),接口调用失败的回调函数
    • completefunction(res),接口调用结束的回调函数(调用成功、失败都会执行)
  • Taro.clearStorage()(object),清理本地数据缓存。

    • 参数:object
    • successfunction(res),接口调用成功的回调函数
    • failfunction(err),接口调用失败的回调函数
    • completefunction(res),接口调用结束的回调函数(调用成功、失败都会执行)

image-20240731121602707

进阶

自定义组件

组件及生命周期

在 Taro 中,除了应用和页面组件有生命周期之外, Taro 的组件也是生命周期,如下图所示:

image-20240815124114495

下面我们来编写一个 HYButton 组件。

1、创建组件

image-20240815143957746

使用组件

image-20240815145314470

2、定义属性

3、样式编写

  • 依赖包:

    • classnames
    • proptypes
  • 启用设置:开启缓存、启用mini和h5的cssModules

    image-20240815144309527

  • xxx.modules.scss中编写样式

    image-20240815144809482

  • 导入scss样式

    image-20240815145259649

image-20240815145327322

4、定义插槽

image-20240815145439463

使用

image-20240815145447846

5、定义事件

  • 组件内部定义一个click事件,并向外发射一个onBtnClick的事件

    image-20240815145746492

  • 组件外监听传递出来的事件onBtnClick

    image-20240815150035659

6、定义组件生命周期和页面生命周期

  • 组件生命周期:useEffect

    image-20240815150212719

  • 页面生命周期:useLoad、useDidShow、useReady

    image-20240815150405690

注意: 在组件中编写页面生命周期的支持情况:

  • class 组件默认不行,需要单独处理

  • 但是函数组件是支持的

跨端兼容实现

跨端兼容方案

Taro 的设计初衷就是为了统一跨平台的开发方式,并且已经尽力通过运行时框架、组件、API 去抹平多端差异,但是由于不同的平台之间还是存在一些无法消除的差异,所以为了更好的实现跨平台开发,Taro 中提供了如下的解决方案。

方案一:内置环境变量

  • Taro 在编译时提供了一些内置的环境变量来帮助用户做一些特殊处理。

  • 通过这个变量来区分不同环境,从而使用不同的逻辑。在编译阶段,会移除不属于当前端的代码,只保留当前端的代码。

  • 内置环境变量虽然可以解决大部分跨端的问题,但是会让代码中存在很多逻辑判断的代码,影了响代码的可维护性,而且也让代码变得丑陋

  • 为了解决这种问题,Taro 提供了另外一种跨端开发的方式作为补充。

方案二:统一接口的多端文件

  • 开发者可以通过将文件修改成 原文件名 + 端类型 的命名形式(端类型对应着 process.env.TARO_ENV 的取值),不同端的文件代码对外保持统一接口,而引用的时候仍然是 import 原文件名的文件。

  • Taro 在编译时,会跟根据当前编译平台类型,精准加载对应端类型的文件,从而达到不同的端加载其对应端的文件。

内置环境变量

内置环境变量( process.env.TARO_ENV),该环境变量可直接使用

  • process.env.TARO_ENV: 用于判断当前的编译平台类型,有效值为:weapp / swan / alipay / tt / qq / jd / h5 / rn

  • 通过这个变量来区分不同环境,从而使用不同的逻辑。

  • 在编译阶段,会移除不属于当前平台的代码,只保留当前平台的代码,例如:

注意: 不要解构 process.env 来获取环境变量,请直接以完整书写的方式(process.env.TARO_ENV)来进行使用。

image-20240815152101366

image-20240815152339616

统一接口的多端文件

统一接口的多端文件这一跨平台兼容写法有如下三个使用要点:

  • 1、不同端的对应文件一定要统一接口和调用方式

  • 2、引用文件的时候,只需写默认文件名,不用带文件后缀

  • 3、最好有一个平台无关的默认文件,这样在使用 TS 的时候也不会出现报错。

常见有以下使用场景:

  • 多端组件(属性,方法,事件等需统一)

    • 针对不同的端写不同的组件代码
  • 多端脚本逻辑(属性、方法等需统一)

    • 针对不同的端写不同的脚本逻辑代码

image-20240731121908905

多端脚本

  • index.js

    image-20240815154843461

  • index.h5.js

    image-20240815155001761

  • index.weapp.js

    image-20240815155051077

  • 使用

    image-20240815155331515

Redux

认识RTK

依赖包:

  • react-redux
  • @reduxjs/toolkit

安装:

sh
pnpm i @reduxjs/toolkit react-redux

Redux Toolkit 是官方推荐的编写 Redux 逻辑的方法。

  • 以前我们在使用 redux 的时候,通常会将 redux 代码拆分在多个文件中,比如:constants、action、reducer 等

  • 这种代码组织方式过于繁琐和麻烦,导致代码量过多,也不利于后期管理

  • Redux Toolkit 就是为了解决这种编码方式而诞生。

  • 并且以前的 createStore 方式已标为过时,而 Redux Toolkit 已成为官方推荐

API

Redux Toolkit的核心API主要是如下几个:

  • configureStore({ reducer, middleware, devTools, ... })返回:store,包装createStore以提供简化的配置选项和良好的默认值。它可以自动组合你的 slice reducer,添加你提供的任何 Redux 中间件,redux-thunk默认包含,并启用 Redux DevTools Extension。
    • 参数
    • reducer:``,Redux store 的根 reducer
    • middleware:``,要使用的中间件数组
    • devTools:``,是否启用开发工具(如 Redux DevTools),默认true
    • preloadedState:``,初始状态
    • enhancers:``,其他 store 增强器
    • 返回
    • store:``,返回的是一个 Redux store 实例,而不是一个类。因此无法创建多个 store 实例
  • createSlice({ name, initialState, reducers,... })返回:reducerSlice,用于创建一个Redux reducer和action creator的集合
    • 参数
    • nameString,用于标识这个reducer的名称,action.type会根据name生成
    • initialStateany,表示这个reducer的初始状态
    • reducers{ reducer,... },用于定义这个reducer的action creator和对应的reducer函数
      • reducer(state, action) => void,相当于之前的reducer函数
    • extraReducers: { reducer,... },包含了与当前slice无关的reducer函数
      • reducer(state, action) => void,相当于之前的reducer函数
    • 返回
    • reducerSlice:``,返回一个reducer片段
  • createAsyncThunk(typePrefix, payloadCreator, options? )返回:,用于创建一个异步action creator
    • 参数
    • typePrefixString,用于标识这个异步action creator的类型前缀
    • payloadCreator(arg, thunkAPI) => Promise,用于处理异步操作并返回一个Promise对象
    • options?Object,用于配置异步action creator的一些选项
      • fulfilled:用于指定异步操作成功时的处理函数。
      • rejected:用于指定异步操作失败时的处理函数。
      • pending:用于指定异步操作进行中时的处理函数。
      • dispatchCondition:用于指定在什么条件下才会dispatch这个action的函数。
      • condition:用于指定在什么条件下才会调用payloadCreator函数的函数。
      • typeSuffixes:用于指定异步action creator的类型后缀的对象。
      • serializeError:用于指定如何序列化异步操作的错误信息的函数。

创建 counter 模块的 reducer

我们先创建 counter 模块的 reducer: 通过 createSlice 创建一个 slice。

createSlice({ name, initialState, reducers,... })返回:reducerSlice,用于创建一个Redux reducer和action creator的集合

  • 参数
  • nameString,用于标识这个reducer的名称,action.type会根据name生成
  • initialStateany,表示这个reducer的初始状态
  • reducers{ reducer,... },用于定义这个reducer的action creator和对应的reducer函数
    • reducer(state, action) => void,相当于之前的reducer函数
  • extraReducers: { reducer,... },包含了与当前slice无关的reducer函数
    • reducer(state, action) => void,相当于之前的reducer函数
  • 返回
  • reducerSlice:``,返回一个reducer片段

image-20240731121948747

store 的创建

configureStore({ reducer, middleware, devTools, ... })返回:store,包装createStore以提供简化的配置选项和良好的默认值。它可以自动组合你的 slice reducer,添加你提供的任何 Redux 中间件,redux-thunk默认包含,并启用 Redux DevTools Extension。

  • 参数
  • reducer:``,Redux store 的根 reducer
  • middleware:``,要使用的中间件数组
  • devTools:``,是否启用开发工具(如 Redux DevTools),默认true
  • preloadedState:``,初始状态
  • enhancers:``,其他 store 增强器
  • 返回
  • store:``,返回的是一个 Redux store 实例,而不是一个类。因此无法创建多个 store 实例

image-20240731122014975

store 接入应用

在 app.js 中将 store 接入应用:

  • Provider,内容提供者,给所有的子或孙子组件提供 store 对象;

  • store: 使用 configureStore 创建的 store 对象;

image-20240815162029493

开始使用 store

在函数式组件中可以使用 react-redux 提供的 Hooks API 连接、操作 store。

1、useSelector 允许你使用 selector 函数从 store 中获取数据(root state)。

image-20240815162619946

2、useDispatch 返回 redux store 的 dispatch 引用。你可以使用它来 dispatch actions。

image-20240815163354855

image-20240815163358716

image-20240815163401455

3、useStore 返回一个 store 引用,和 Provider 组件引用完全一致。

image-20240731122040915

Redux Toolkit 异步 Action 操作

在之前的开发中,我们通过 redux-thunk 中间件让 dispatch 中可以进行异步操作。

Redux Toolkit 默认已经给我们继承了 Thunk 相关的功能:createAsyncThunk

createAsyncThunk(typePrefix, payloadCreator, options? )返回:,用于创建一个异步action creator

  • 参数
  • typePrefixString,用于标识这个异步action creator的类型前缀
  • payloadCreator(arg, thunkAPI) => Promise,用于处理异步操作并返回一个Promise对象
  • options?Object,用于配置异步action creator的一些选项
    • fulfilled:用于指定异步操作成功时的处理函数。
    • rejected:用于指定异步操作失败时的处理函数。
    • pending:用于指定异步操作进行中时的处理函数。
    • dispatchCondition:用于指定在什么条件下才会dispatch这个action的函数。
    • condition:用于指定在什么条件下才会调用payloadCreator函数的函数。
    • typeSuffixes:用于指定异步action creator的类型后缀的对象。
    • serializeError:用于指定如何序列化异步操作的错误信息的函数。

image-20240731122050861

当 createAsyncThunk 创建出来的 action 被 dispatch 时,会存在三种状态:

  • pending:action 被发出,但是还没有最终的结果;

  • fulfilled:获取到最终的结果(有返回值的结果);

  • rejected:执行过程中有错误或者抛出了异常;

我们可以在 createSlice 的 entraReducer 中监听这些结果:见下图

image-20240731122103916

builder写法:

image-20240815164759914

在组件中触发异步action

image-20240815164031626