写在前面
最近写微信小程序的项目,用到了Taro框架。下面进行一下总结
介绍
Taro 是一套遵循 React 语法规范的 多端开发 解决方案。
使用 Taro,我们可以只编写一套代码,再通过 Taro 的编译工具,将源代码分别编译出可以在不同端(微信/百度/支付宝 等)运行的代码。
快速开始
由于小编在开发的过程中,只转成了微信端小程序,所以重点会总结微信小程序相关的注意点。
如果您也需要转微信端小程序的话,请先下载微信开发者工具,附上链接:developers.weixin.qq.com/miniprogram… 推荐下载稳定版哦 Stable Build (1.02.1911180)
开始前的小插曲
在运行中报错,报错如下:
当时是同一套代码,跑在两个不同的电脑发生的问题。所以开始从环境找问题。然后开始找原因,各种对本版本号,刚开始以为是微信开发者工具的版本号,然鹅并不是。最后终于定位到问题了, 原因是由于taro的版本问题,当时电脑上下载的是最新版本的taro v1.3.26 ,最后换成了 v1.3.19便解决了!!! 咱啥也不敢说,啥也不敢问。
Taro开发规范
在开发前,建议先阅读开发前的规范及JavaScript书写规范,下面是比较重要的一些规范。
1. 所有内置组件均需要引入后再使用
例如:
import Taro, { Component } from '@tarojs/taro'
import { View } from '@tarojs/components'
export default class PartnerIn extends Component {
render () {
return (
<View className='test'> // 正确
<Text>我是一个text</Text> // 错误
</View>
)
}
}
2. 推荐使用对象解构的方式来使用 state、props
例如:
import Taro, { Component } from '@tarojs/taro'
import { View, Input } from '@tarojs/components'
export default class SignOn extends Component {
this.state = {
bankName: ''
}
render () {
const { isEnable } = this.props.signOnInfoStore // 正确
const { bankName } = this.state // 正确
return (
<View className='test'>
{isEnable && <Text className='span'>{bankName}</Text>}
</View>
)
}
}
3. 事件绑定均以 on 开头
在 Taro 中所有默认事件如 onClick、onTouchStart 等等,均以 on 开头
4.父子组件传入函数时属性名需要以 on 开头
例如:
import Taro, { Component } from '@tarojs/taro'
import { View, Input } from '@tarojs/components'
import Tab from '../../components/Tab/Tab'
export default class MyComponent extends Component {
clickHandler (e) {
console.log(e)
}
render () {
return (
<View className='test'>
<Tab onChange={this.clickHandler} /> // 正确
</View>
)
}
}
5.不能使用 Array#map 之外的方法操作 JSX 数组
Taro 在小程序端实际上把 JSX 转换成了字符串模板,而一个原生 JSX 表达式实际上是一个 React/Nerv 元素(react-element)的构造器,因此在原生 JSX 中你可以随意地对一组 React 元素进行操作。但在 Taro 中你只能使用 map 方法,Taro 转换成小程序中 wx:for
所以需要先在遍历数组之间处理好数据,然后在调用map来遍历
render () {
...
driverList.push(...data)
...
return (
<View>
driverList.map(item=>{
return (<View>{item.name}</View>)
})
</View>
)
}
6. 钩子的书写顺序
在 Taro 组件中会包含类静态属性、类属性、生命周期等的类成员,其书写顺序最好遵循以下约定(顺序从上至下)
- static 静态方法
- constructor
- componentWillMount
- componentDidMount
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- componentDidUpdate
- componentWillUnmount
- 点击回调或者事件回调 比如 onClickSubmit() 或者 onChangeDescription()
- render
上面列举了一些比较重要的书写规范及需要注意的事项,下面来总结一下比较重要的 生命周期
生命周期
componentWillMount
对应的是微信小程序中对应页面的onLoad或入口文件app中的onLaunch
监听程序初始化,初始化完成时触发(全局只触发一次)意思就是componentWillMount会在render之前执行,并且只执行一次。
由于这个方法始终只执行一次,所以如果在这里定义了setState方法之后,页面永远都只会在加载前更新一次。 在这里可以直接获取到this.$router.params,但是取不到this.props最新的值。
componentDidMount
对应的是微信小程序中对应页面的onReady或入口文件app中的onLaunch,在 componentWillMount后执行
这个钩子是在render之后执行,并且只会执行一次。在这里可以获取到dom元素。
componentDidShow
该方法对应的是微信小程序里面的onShow
在页面可见时,执行一次
componentDidHide
该方法对应的是微信小程序里面的onHide
与上面方法相反,该方法是在页面不可见的时候执行一次
componentDidCatchError
错误监听函数,对应微信小程序中的 onError方法
程序发生脚本错误或 API 调用报错时触发,也可以使用 Taro.onError 绑定监听
componentDidNotFound
对应微信小程序中的 onPageNotFound方法
当要打开的页面不存在时,就会触发该函数。也可以使用 Taro.onPageNotFound 绑定监听
shouldComponentUpdate(nextProps, nextState)
页面是否需要更新
当你清楚在某些情况下组件不需要被重新渲染时,可以通过在shouldComponentUpdate 钩子里返回 false 来跳过本次渲染流程。可以通过此钩子来进行性能优化
shouldComponentUpdate (nextProps, nextState) {
if (this.props.color !== nextProps.color) {
return true
}
if (this.state.count !== nextState.count) {
return true
}
return false
}
componentWillUpdate(nextProps, nextState)
页面即将更新
componentDidUpdate(prevProps, prevState)
页面更新完毕
componentWillUnmount
页面退出,对应微信小程序中的 onUnload方法
如 redirectTo 或 navigateBack 到其他页面时,用来执行一些清理任务,比如setTimeout等函数
页面上的一些专属方法
onPullDownRefresh
监听用户下拉刷新事件
- 需要在全局配置的 window 选项中或页面配置中开启 enablePullDownRefresh
config = {
enablePullDownRefresh: true
}
- 可以通过 Taro.startPullDownRefresh 触发下拉刷新,调用后触发下拉刷新动画,效果与用户手动下拉刷新一致。
- 当处理完数据刷新后,Taro.stopPullDownRefresh 可以停止当前页面的下拉刷新
onReachBottom
监听用户上拉触底事件
- 可以在全局配置的 window 选项中或页面配置中设置触发距离 onReachBottomDistance
config = {
onReachBottomDistance: 50
}
- 在触发距离内滑动期间,本事件只会被触发一次
onShareAppMessage(Object)
用户点击右上角转发按钮或者是点击页面内转发按钮(Button 组件 openType='share')时触发
! 注意:只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮
Object 参数说明:
- from: 转发事件来源。
-button:页面内转发按钮;
-menu:右上角转发菜单 - target: 如果 from 值是 button,则 target 是触发这次转发事件的 button,否则为 undefined
- webViewUrl: 页面中包含 组件时,返回当前 的url
此方法,需要return 一个对象,用于自定义转发内容
onShareAppMessage(res){
const { captainInfo } = this.props.homeStore
let shareData = {
title: `快狗超级队长${captainInfo.name || ''}发券了`,
path: '/pages/ShareCouponList/index',
imageUrl: 'https://static.daojia.com/assets/project/tosimple-pic/beijing-1_xxxxx.png',
}
if(res.from == 'button'){ // 页面内按钮点击分享
shareData.path = '/pages/ShareCoupons/index?id='+this.state.couponIds
}
return shareData
}
onPageScroll(Object)
当用户滑动页面时触发
Object 参数说明:
- scrollTop: 页面在垂直方向已滚动的距离(单位px)
! 注意:请只在需要的时候才在 page 中定义此方法,不要定义空方法。以减少不必要的事件派发对渲染层-逻辑层通信的影响。
! 注意:请避免在 onPageScroll 中过于频繁的执行 this.setState() 等引起逻辑层-渲染层通信的操作。尤其是每次传输大量数据,会影响通信耗时。
onTabItemTap(Object)
当前是 tab 页时,点击 tab 时触发
Object 参数说明:
- index:被点击 tabItem 的序号,从 0 开始
- pagePath:被点击 tabItem 的页面路径
- text:被点击 tabItem 的按钮文字
componentWillPreload
预加载的钩子,目前只在微信小程序里面可用
在这个钩子里面可以进行性能优化
在微信小程序里从调用 Taro.navigateTo、Taro.redirectTo 或 Taro.switchTab 后,到页面触发 componentWillMount 会有一定延时。因此一些网络请求可以提前到发起跳转前一刻去请求。
Taro 提供了 componentWillPreload 钩子,它接收页面跳转的参数作为参数。可以把需要预加载的内容通过 return 返回,然后在页面触发 componentWillMount 后即可通过 this.$preloadData 获取到预加载的内容。
注意:调用跳转方法时需要使用绝对路径,相对路径不会触发此钩子。
export default class Index extends Component {
componentWillMount () {
console.log('isFetching: ', this.isFetching)
this.$preloadData
.then(res => {
console.log('res: ', res)
this.isFetching = false
})
}
componentWillPreload (params) {
return this.fetchData(params.url)
}
fetchData () {
this.isFetching = true
...
}
}
总结
开发中小编也遇到了一些问题,当然也都找到了解决方案 emmm~
下面贴一个简单的小问题吧。
先上代码
render(){
const { money, info } = this.state
const p = `可提现${info.availableAmount}元`
return(
<View>
<Text className='label-1'>¥</Text>
{money}
<Input type='digit' value={money} placeholder={p} className='input-money' placeholderClass='input-placeholder' />
</View>
<View>
<Text className='label-blue' onClick={this.allTake.bind(this)}>全部提现</Text>
</View>
)
}
上面这段代码的主要功能是为了实现 既可以输入金额,也可以点击全部提现按钮来设置提现的金额。
allTake(){
// 全部取现
const { availableAmount } = this.state.info
this.setState({
money: availableAmount
})
}
这一部分代码是用来实现点击全部提现,设置金额的方法
重点来了!!! 然鹅,设置不生效,这是什么原因呢?
value 设置的只是一个初始值,在改变input 值的时候,并没有改变 money的值。
接下来就是进行改造啦~
<Input type='digit' onInput={this.moneyInput.bind(this)} value={money} />
添加了一个input函数,来监听input输入值的时候一个操作
该函数的写法
moneyInput(e){
const m = e.target.value;
this.setState({
money: m
})
}
这样就可以完美实现money的值永远都是最新的值,并且可以直接设置money 的值来实现input的值跟着改变。
最后
在积累中成长,欢迎一起交流讨论Taro的学习心得~