快速搭建了一个泰罗
前提:保证 node 版本>=8.0.0
Step1.全局安装 Taro
1
| yarn global add @tarojs/cli
|
Step2.使用命令创建模板项目
Step3.使用 yarn 安装依赖
编译预览及打包
目前我只需要适配微信小程序,所以只对微信小程序进行编译预览及打包
1 2
| yarn dev:weapp --watch yarn build:weapp
|
如果在编译时想禁用 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
|
module.exports = { singleQuote: true, semi: false, arrowParens: 'always', trailingComma: 'es5', };
|
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: '忘记密码', };
render() { const {} = this.props; const {} = this.state; return ( <View className='page'> <Text>Hello Taro</Text> </View> ); } } export default LoginFindpassword;
|
与微信小程序原生写法的常见不同写法
1
| <Input bindfocus={this.onFocus} /> => <Input onFocus={this.onFocus} />
|
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 指南-编译模板出错
如何快速重构
同样的内容同时开发,就是高效解决问题的办法!划分合并的思想!
- 写入 Taro 页面模板
- 写入 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)
|
- 写入生命周期方法
- 写入 js 方法
- 删除{}=state 中无效数值 4.全局修改
setData
=>setState
wx.
=>Taro.
.data.
=>.state.
- 注意 res.data 不要改成了 res.state
: function(e)
=>=(e)=>
5.全局修改: function()
=>=()=>
(fail、success 等除外)
- },的,去掉
- onLoad 的 options 参数改用路由传参
- app.jsx 设置页面路径
检查 json 命名
检测 setState
getCurrentPages、prevPage 修改
完成倒计时
发布
在 run bulid 后选择 dist 文件夹进行上传发布即可