0%

Taro 使用指南

Taro 就是可以用 React 语法写小程序的框架,拥有多端转换能力,一套代码可编译为微信小程序、百度小程序、支付宝小程序、H5、RN 等

1、入门

1.1、安装 CLI 及项目初始化

1
2
npm install -g @tarojs/cli
taro init 项目名

image

可以选择使用 SCSS 、TS、Redux

1.2、编译至各种平台

1
2
3
4
5
6
7
// 编译为小程序
npm run dev:weapp
npm run build:weapp
// 编译为 H5
npm run dev:h5
// 编译为 RN
npm run dev:rn

编译为小程序时,小程序代码位于 dist 目录下

1.3、微信小程序须知

  • 小程序注册

    注册地址,注意一个邮箱只能注册一个小程序
  • 小程序后台

    后台地址,后台可查看当前小程序版本,添加开发者,查看小程序 AppID 和 AppSecret 等功能
  • 小程序开发者工具

    下载地址
  • 小程序开发流程

    1、在开发者工具中新建项目,填入对应的 AppID

    2、在小程序后台配置服务器域名(开发-服务器域名)
  • 小程序发布流程

    1、在开发者工具中上传代码

    2、在管理后台-版本管理-开发版本中提交审核,注意提交审核前可先生成体验版,确认体验版没问题后再提交审核

2、注意点

由于 Taro 编译后的代码已经经过了转义和压缩,因此还需要注意微信开发者工具的项目设置

image

  • 只能在 render 里使用 jsx 语法
  • 不能在包含 JSX 元素的 map 循环中使用 if 表达式
    尽量在 map 循环中使用条件表达式或逻辑表达式
  • 不能使用 Array.map 之外的方法操作 JSX 数组
    先处理好需要遍历的数组,然后再用处理好的数组调用 map 方法。
  • 不能在 JSX 参数中使用匿名函数
    使用 bind 或 类参数绑定函数。
  • 不能在 JSX 参数中使用对象展开符
    开发者自行赋值:
1
2
<View {...props} />  // wrong
<View id={id} title={title} /> // ok
  • 不允许在 JSX 参数(props)中传入 JSX 元素
  • 不支持无状态组件(Stateless Component)
  • 函数名驼峰,且不能包含数字,不能以下划线开始或结尾以及长度不超过20
  • 必须使用单引号,不支持双引号
  • 对于 process.env,建议直接书写 process.env.NODE_ENV,而不是解构
  • 组件传递函数属性名以 on 开头
  • 小程序端不要将在模板中用到的数据设置为 undefined
  • 小程序端不要在组件中打印 this.props.children
  • 组件属性传递注意

    不要以 id、class、style 作为自定义组件的属性与内部 state 的名称,因为这些属性名在微信小程序中会丢失。
  • 组件 state 与 props 里字段重名的问题

    不要在 state 与 props 上用同名的字段,因为这些被字段在微信小程序中都会挂在 data 上。
  • 小程序中页面生命周期 componentWillMount 不一致问题
  • 组件的 constructor 与 render 提前调用

3、Taro 实战

3.1、相关库介绍

  • @tarojs/taro

    taro 核心库,相当于 react
1
2
3
import Taro, { Component } from '@tarojs/taro'
class App extends Component {}
Taro.render(<App />, document.getElementById('app'))
  • @tarojs/redux
    taro 状态管理辅助库,相当于 react-redux
1
import { Provider,connect  } from '@tarojs/redux'
  • @tarojs/components
    taro 为屏蔽多端差异而制定的标准组件库,在 taro 中不能直接写常规的 HTML 标签,而必须用这个组件库里的标签,就像写 RN 一样:
1
2
3
4
5
6
7
import { View, Button, Text } from "@tarojs/components";
<View className='index'>
<Button className='add_btn' onClick={this.props.add}>
+
</Button>
<Text> Hello, World </Text>
</View>
  • @tarojs/async-await
    taro 支持 async await 写法库
  • taro-ui
    taro 为屏蔽多端差异而制定的业务组件库,比如 Tabs,Modal,Menu 之类的常用的业务组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { AtTabs, AtTabsPane } from "taro-ui";
<AtTabs
current={this.state.current}
tabList={tabList}
onClick={this.handleClick.bind(this)}
>
<AtTabsPane current={this.state.current} index={0}>
<AllContainer />
</AtTabsPane>
<AtTabsPane current={this.state.current} index={1}>
<View style='padding: 100px 50px;background-color: #FAFBFC;text-align: center;'>
标签页二的内容
</View>
</AtTabsPane>
<AtTabsPane current={this.state.current} index={2}>
<View style='padding: 100px 50px;background-color: #FAFBFC;text-align: center;'>
标签页三的内容
</View>
</AtTabsPane>
</AtTabs>

3.2、常用工具类封装

  • 本地存储
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Taro from "@tarojs/taro";

class Store {
removeItem(key) {
return Taro.removeStorageSync(key);
}
getItem(key) {
return Taro.getStorageSync(key);
}
setItem(key, value) {
return Taro.setStorageSync(key, value);
}
clear() {
return Taro.clearStorageSync();
}
}

export default new Store();
  • 请求封装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import Taro from '@tarojs/taro'
import {
API_USER_LOGIN
} from '@constants/api'

const CODE_SUCCESS = '200'
const CODE_AUTH_EXPIRED = '600'

function getStorage(key) {
return Taro.getStorage({
key
}).then(res => res.data).catch(() => '')
}

function updateStorage(data = {}) {
return Promise.all([
Taro.setStorage({
key: 'token',
data: data['3rdSession'] || ''
}),
Taro.setStorage({
key: 'uid',
data: data['uid'] || ''
})
])
}

/**
* 简易封装网络请求
* // NOTE 需要注意 RN 不支持 *StorageSync,此处用 async/await 解决
* @param {*} options
*/
export default async function fetch(options) {
const {
url,
payload,
method = 'GET',
showToast = true
} = options
const token = await getStorage('token')
const header = token ? {
'WX-PIN-SESSION': token,
'X-WX-3RD-Session': token
} : {}
if (method === 'POST') {
header['content-type'] = 'application/json'
}

return Taro.request({
url,
method,
data: payload,
header
}).then(async (res) => {
const {
code,
data
} = res.data
if (code !== CODE_SUCCESS) {
if (code === CODE_AUTH_EXPIRED) {
await updateStorage({})
}
return Promise.reject(res.data)
}

if (url === API_USER_LOGIN) {
await updateStorage(data)
}
return data
}).catch((err) => {
const defaultMsg = err.code === CODE_AUTH_EXPIRED ? '登录失效' : '请求异常'
if (showToast) {
Taro.showToast({
title: err && err.errorMsg || defaultMsg,
icon: 'none'
})
}

return Promise.reject({
message: defaultMsg,
...err
})
})
}

3.3 常用 API 介绍

  • 授权
1
2
3
4
5
6
7
8
9
<Button
className='btn-max-w'
plain
type='primary'
open-type='getUserInfo'
onGetUserInfo={this.handleUserInfo}
>
授权
</Button>
  • 获取位置
1
Taro.getLocation({type:'gcj02'}).then(data=>console.log(data))
  • 操作反馈
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Taro.showToast({
title: "成功",
icon: "success"
});

Taro.setTabBarBadge({ index: 1, text: "1" });

Taro.showLoading({
title: "加载中..."
}).then(res =>
setTimeout(() => {
Taro.hideLoading();
}, 2000)
);

4、其他问题记录

  • 设置页面全屏
1
2
3
4
// app.scss
page {
height: 100%;
}
  • Css Modules 支持
    配置 config/index.js 下的 h5 和 weapp 中的 module.cssModules 即可
1
2
3
4
5
6
7
8
// css modules 功能开关与相关配置
cssModules: {
enable: true, // 默认为 false,如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module,下文详细说明
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
  • 配置路径别名
    配置 config/index.js 下的 alias
1
2
3
4
5
6
7
8
9
alias: {
'components': path.resolve(__dirname, '..', 'src/components'),
'pages': path.resolve(__dirname, '..', 'src/pages'),
'store': path.resolve(__dirname, '..', 'src/store'),
'constants': path.resolve(__dirname, '..', 'src/constants'),
'api': path.resolve(__dirname, '..', 'src/api'),
'assets': path.resolve(__dirname, '..', 'src/assets'),
'utils': path.resolve(__dirname, '..', 'src/utils'),
},
  • 多端兼容性问题,引入 lodash 包,支付宝不支持

引入 utils.js 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
global.Object = Object
global.Array = Array
global.Buffer = Buffer
global.DataView = DataView
global.Date = Date
global.Error = Error
global.Float32Array = Float32Array
global.Float64Array = Float64Array
global.Function = Function
global.Int8Array = Int8Array
global.Int16Array = Int16Array
global.Int32Array = Int32Array
global.Map = Map
global.Math = Math
global.Promise = Promise
global.RegExp = RegExp
global.Set = Set
global.String = String
global.Symbol = Symbol
global.TypeError = TypeError
global.Uint8Array = Uint8Array
global.Uint8ClampedArray = Uint8ClampedArray
global.Uint16Array = Uint16Array
global.Uint32Array = Uint32Array
global.WeakMap = WeakMap
global.clearTimeout = clearTimeout
global.isFinite = isFinite
global.parseInt = parseInt
global.setTimeout = setTimeout
  • 打包微信,支付宝出问题

npm 包版本不统一导致

1
2
3
4
5
6
7
8
9
10
11
12
13
"dependencies": {
"@tarojs/components": "3.0.18",
"@tarojs/react": "3.0.18",
"@tarojs/runtime": "3.0.18",
"@tarojs/taro": "3.0.18",
},
"devDependencies": {
"@tarojs/cli": "3.0.18",
"@tarojs/mini-runner": "3.0.18",
"@tarojs/webpack-runner": "3.0.18",
"babel-preset-taro": "3.0.18",
"eslint-config-taro": "3.0.18",
},
  • 全局 scss 设置,

config.js 中可以设置,但是必须要重新启动才可以

1
2
3
sass: {
resource: path.resolve(__dirname, '..', 'src/assets/styles/global.scss'),
},
  • 设置代理问题

nginx 配合 fiddler 代理转发可以实现本地开发,app 端进行调试

  • 手机页面头部点击返回,不能触发页面生命周期

可以通过 componentDidShow 或者 useDidShow 实现

  • map 结构存储订单数据(存储二维数组)

用法实现 order.get(status)

  • 不同业务线的状态扭转问题

利用回调函数,函数式编程实现

  • 地图坐标系问题

百度(bd09ll)、高德(gcj02)、腾讯(gcj02)

  • 轨迹渲染问题

polyline, label, marker

动态设置展示区域

includePoints,并且通过 updateComponent 强制渲染,手机端和开发工具展示不一致问题

1
2
3
4
5
6
7
8
9
10
11
12
13
this.mapCtx.updateComponents({
markers,
includePoints,
polyline,
longitude: cLocation.lng,
latitude: cLocation.lat,
setting: {
showCompass: 0,
showScale: 0,
gestureEnable: 1,
tiltGesturesEnabled: 0,
},
})
  • 处理多个不同任务的定时器,清除问题

static 静态局部变量

  • 发布订阅者模式,处理登陆问题

发布订阅的 service 类库封装

  • 定时器(汽车位置,订单状态,订单详情,支付状态),状态扭转类,支付类

类封装