初识泰罗奥特曼

快速搭建了一个泰罗

前提:保证 node 版本>=8.0.0

Step1.全局安装 Taro

1
yarn global add @tarojs/cli

Step2.使用命令创建模板项目

1
taro init MyFirstTaro

Step3.使用 yarn 安装依赖

1
2
cd MyFirstTaro
yarn

编译预览及打包

目前我只需要适配微信小程序,所以只对微信小程序进行编译预览及打包

1
2
yarn dev:weapp --watch # 添加watch来监听文件修改
yarn build:weapp # build 模式:无--watch,将不会监听文件修改,并会对代码进行压缩打包

如果在编译时想禁用 ESLint 检查,可以在命令前加入 ESLINT=false 参数

1
ESLINT=false taro build --type weapp --watch

文件配置

格式化工具

VsCode 安装好格式化插件 prettierrc 的前提下

.prettierrc.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 默认的一些配置
* printWidth: 80,
* tabWidth: 2,
* useTabs: false
* quoteProps:as-needed 对象的属性只有需要时才添加引号
* jsxSingleQuote: false jsx中使用单引号
* trailingComma: none 数组和对象的尾逗号
* bracketSpacing: true 对象左右大括号各有一个空格 { foo: bar }
* jsxBracketSameLine: false jsx中标签多行属性的第一个 > 是单独一行还是在行尾
* arrowParens: avoid 箭头函数只有一个参数时,尽可能地省略括号
*/
module.exports = {
singleQuote: true, // 单引号
semi: false,
arrowParens: 'always',
trailingComma: 'es5', // 是否使用尾逗号,有三个可选值:<none|es5|all>
};
// 无分号,箭头函数参数必有括号,尾逗号

project.config.json 配置
Taro 模板创建的项目默认拥有 project.config.json 这一项目配置文件只用于适配微信小程序,要适配其他平台要进行相应 json 文件的配置,具体可看Taro 官网-项目配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"miniprogramRoot": "dist/",
"projectname": "MyFirstTaro",
"description": "Can't Tell U",
"appid": "wxf694b87c0666666",
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false,
"coverView": true,
"babelSetting": {
"ignore": [],
"outputPath": ""
}
},
"compileType": "miniprogram",
"simulatorType": "wechat",
"simulatorPluginLibVersion": {},
"condition": {}
}

Taro 页面模板

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
import Taro, { Component } from '@tarojs/taro';
import { View, Text } from '@tarojs/components';
import './app.less';
import './index.less';

class LoginFindpassword extends Component {
constructor(props) {
super(props);
this.state = {};
}
componentWillMount() {
console.log('this.$router.params');
console.log(this.$router.params);
}
componentDidMount() {}
componentDidHide() {}
componentDidShow() {}
// 项目配置
config = {
navigationBarTitleText: '忘记密码',
};

// JS方法
render() {
const {} = this.props;
const {} = this.state;
return (
<View className='page'>
<Text>Hello Taro</Text>
</View>
);
}
}
export default LoginFindpassword;

与微信小程序原生写法的常见不同写法

  • bindfocus 改用 onFocus 替代
1
<Input bindfocus={this.onFocus} />  => <Input onFocus={this.onFocus} />
  • bindtap 改用 onClick 替代
1
<View bindtap={this.onTag} /> => <View onClick={this.onTag} />
  • animationEnd 改用 onAnimationEnd 替代
1
<CustomElement animationEnd={this.data.onAnimationEnd} /> => <CustomElement onAnimationEnd={this.state.onAnimationEnd} />
  • bindchange 该用 onChange 替代
  • placeholder=””改用 placeholder={} 替代
  • maxlength=”15”改用 maxLength={15}替代
  • scroll-view 改为 ScrollView
  • input 中password改写为<Input password={true} />
  • bindinput改写为onInput
  • cover-View改写为CoverView
  • <block>...</block>改写为<Block>...</Block>
  • <picker>...</picker>改写为<Picker>...</Picker>
  • wx:if={IdCardType == 1010106}改为{IdCardType === 1010106 && (...)}
  • this.setData改为this.setState
  • 在小程序里对应的生命周期是 onLoad 在 Taro 中对应 componentWillMount()这一块
  • onLoad 中的 query 改为路由传参this.$router.params
  • 在小程序里对应的生命周期是 onShow 在 Taro 中对应 componentDidShow()这一块
  • 在小程序里对应的生命周期是 onLaunch 在 Taro 中对应 componentDidMount()这一块(在 componentWillMount 后执行)
    监听程序初始化,初始化完成时触发(全局只触发一次)
  • 页面退出时在小程序里对应的生命周期是 onUnload 在 Taro 中对应 componentWillUnmount()这一块
  • 动态修改 title:
1
2
3
Taro.setNavigationBarTitle({
title: '登录'
});
  • 使用map方法替换成小程序中wx:for,且要注意 Taro 中 map 后索引通过 map(item,index)后给对应事件通过 bind(this,index)的方式获取索引 index,而不能使用小程序常用的自定义方法’data-xxx’ 微信原生
1
2
3
<view className="route-list" wx:for={orderList} wx:for-item="order" bindtap="routeChoosedTap" data-id={index} wx:key="orderList">
{{order.test}}
</view>

Taro

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
orderList.map((order, index) => {
return (
<View
className='route-list'
onClick={this.routeChoosedTap}
data-id={index}
taroKey='orderList'
>
{order.test}
</View>
);
});
}
  • taroKey 替换微信小程序的 wx:key,用于循环渲染原生小程序组件,赋予每个元素唯一确定标识

原生

1
<view wx:key={statusArr}>{item.message}</view>

Taro

1
<view taroKey={statusArr}>{item.message}</view>

你不得不避免的坑

因为 setState 异步导致的问题

this.data.orderList = []时会直接操作 data 中的数据,而 React 语法使用 setState 是有延时的,所以要放在 setState 的会提到中执行

场景:
登录成功则通过 Taro.setStorage 缓存一个 key,并将 hasLogin 设置为 true
首页通过 getStorage 来获取指定 key 来判断是否登录成功
如果在 complete 中通过 setState 更新 hasLogin,但 setState 是异步操作,所以 getStorage 事件里获取的 hasLogin 还是 false,所以页面登录进去又会跳回登录页面(login/index)!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Taro.getStorage({
key: 'User',
success: function (res) {
if (res.data) {
globalData.User = res.data;
console.log('成功得到key');
that.setState({
hasLogin: true,
});
}
},
complete: function () {
// 无论接口调用结束的回调函数
if (!that.state.hasLogin) {
console.log('Test3');
console.log(that.state.hasLogin);
Taro.redirectTo({
url: '../login/index',
});
}
},
});

解决方案

不在 complete 回调中使用路由跳转方法,转而放到 componentDidMount()生命周期中执行判断

1
2
3
4
5
6
7
8
9
componentDidMount() {
if (!that.state.hasLogin) {
console.log("Test3");
console.log(that.state.hasLogin);
Taro.redirectTo({
url: "../login/index"
});
}
}

要使用 stopPropagation 来取代 catchtap 阻止冒泡

微信小程序写法

1
2
3
4
5
6
7
8
toggleDialog:function() {
this.setData({
showDialog: false,
})
}
<View className='item-bd' catchtap='toggleDialog'>
{personCenter[yuyan].cancel}
</View>

Taro 写法

1
2
3
4
5
6
7
8
9
toggleDialog = (e) => {
e.stopPropagation();
this.setState({
showDialog: false,
});
};
<View className='item-bd' onClick={this.toggleDialog}>
{personCenter[yuyan].cancel}
</View>;

本地资源引入

小程序样式中引用本地资源

本地 config 文件夹下的 index.js 保持和 Taro 官网中一样的配置,但是使用import note from '../../images/path/note.png仍然报错Failed to load local image resource,仔细检查发现路径也没有任何问题

原因

js 中引入本地图片,Taro 无法对其进行转换

解决方案

在 css 里引入图片

1
2
3
.note {
background-image: url(../../images/note.png);
}

currentTarget 获取索引的 Taro 写法与微信小程序写法异同

场景:后端给出一个数组,数组中的数据依次渲染到列表中,用户点击对应的数据要拿到对应的索引进行操作
微信小程序写法

通过 currentTarget 事件绑定的当前组件,dataset 属性结合自定义属性组成的集合 data-xxx

1
2
3
4
5
6
7
8
9
10
11
//查看审核流程
showCheckModal: function(e){
var that = this;
var id = e.currentTarget.dataset.id;
that.setData({
showCheck: true,
modalList: that.data.orderList[id].ApproveSteps
})
},
<view catchtap="showCheckModal" wx:if="{{order.ApproveSteps.length > 0 }}" data-id="{{index}}">
</view>

Taro 写法

通过 map 将数据遍历渲染,然后通过 bind 将数据的索引传递给绑定事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//查看审核流程
showCheckModal = (index, e) => {
let id = index;
this.setState({
showCheck: true,
modalList: this.state.orderList[id].ApproveSteps,
});
};
{
orderList.length > 0 &&
orderList.map((order, i) => {
return (
<View
className='approveStatus'
onClick={this.showCheckModal.bind(this, i)}
>
<View>{Itinerary[yuyan].viewPro}</View>
</View>
);
});
}

Taro 调用上一个页面方法

关键:.$component.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 返回到个人信息
Taro.showToast({
title: msg,
icon: 'none',
duration: 2000,
success: function () {
let pages = Taro.getCurrentPages();
let prevPage = pages[pages.length - 2];
prevPage.$component.setState(
{
userEmail: email,
},
() => {
console.log('页面回退');
Taro.navigateBack({
delta: 1,
complete: function () {
prevPage.$component.getBaseInfo(globalData.User.UserId);
},
});
}
);
},
});

开发注意事项

  • 在 Taro 默认生成的模板都推荐用 ESLint 进行检测
  • 小程序不支持将 data 中任何一项的 value 设为 undefined,setState 时用null来代替 undefined
  • Taro 中,JS 代码里必须书写单引号,双引号会导致编译错误
  • 双重嵌套遍历时每层的 index 都要写出来,详情Debug 指南-编译模板出错

如何快速重构

同样的内容同时开发,就是高效解决问题的办法!划分合并的思想!

  1. 写入 Taro 页面模板
  2. 写入 wxml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- `"{{` 改为 `{`
- `{{` 改为 `{`
- `}}"` 改为 `}`
- }} 改为 }
- <view 改为<View
- class="改为 className='
- className 的模版字符串引入
- style="改为 style={{
- wx:if 改为{company === 'Mck' && (
- wx:for 参考 Taro 笔记改为 map 遍历
- 全局修改事件
- 所有的 bind 事件修改
- `bindinput="`改写为`onInput={this.`
- `bindtap="`改写为`onClick={this.`
- bindchange 该用 onChange 替代
- maxlength=""改用 maxLength={}替代
- 填充 const {} = this.state
- <label 改为<Label (先引入 Label)
- Checkbox-group 改为<CheckboxGroup (先引入 Checkbox)
- <checkbox 改为<Checkbox (先引入 Checkbox)
- <text 改为<Text (先引入 Text)
  1. 写入生命周期方法
  2. 写入 js 方法
  • 删除{}=state 中无效数值 4.全局修改
  • setData =>setState
  • wx.=>Taro.
  • .data.=>.state.
    • 注意 res.data 不要改成了 res.state
  • : function(e) =>=(e)=> 5.全局修改: function() =>=()=> (fail、success 等除外)
  1. },的,去掉
  2. onLoad 的 options 参数改用路由传参
  3. app.jsx 设置页面路径
    检查 json 命名
    检测 setState
    getCurrentPages、prevPage 修改
    完成倒计时

发布

在 run bulid 后选择 dist 文件夹进行上传发布即可


初识泰罗奥特曼
https://www.pengsifan.com/2019/08/21/初识Taro(泰罗奥特曼)/
作者
Van
发布于
2019年8月21日
许可协议