参考
最佳实践:https://taro-docs.jd.com/taro/docs/best-practice
性能优化:https://taro-docs.jd.com/taro/docs/optimized
官方规范:
组件传递函数属性名以 on 开头
在 v1.3.0-beta.0 之后,自定义组件间的事件传递可以不用 on 开头,但内置组件的事件依然是以 on 开头的,为了一致性我们仍然推荐你以 on 开头命名你的事件。
在 Taro 中,父组件要往子组件传递函数,属性名必须以 on 开头
// 调用 Custom 组件,传入 handleEvent 函数,属性名为 onTriggerclass Parent extends Component {handleEvent () {}render () {return (<Custom onTrigger={this.handleEvent}></Custom>)}}
这是因为,微信小程序端组件化是不能直接传递函数类型给子组件的,在 Taro 中是借助组件的事件机制来实现这一特性,而小程序中传入事件的时候属性名写法为 bindmyevent 或者 bind:myevent
<!-- 当自定义组件触发 myevent 事件时,调用 onMyEvent 方法 --><component-tag-name bindmyevent="onMyEvent" /><!-- 或者可以写成 --><component-tag-name bind:myevent="onMyEvent" />
所以 Taro 中约定组件传递函数属性名以 on 开头,同时这也和内置组件的事件绑定写法保持一致了。
小程序端不要将在模板中用到的数据设置为 undefined
由于小程序不支持将 data 中任何一项的 value 设为 undefined ,在 setState 的时候也请避免这么用。你可以使用 null 来替代。
小程序端不要在组件中打印 this.props.children
在微信小程序端是通过
props 传入 JSX属性名必须以 render 开头
例如,子组件写法
class Dialog extends Component {render () {return (<View className='dialog'><View className='header'>{this.props.renderHeader}</View><View className='body'>{this.props.children}</View><View className='footer'>{this.props.renderFooter}</View></View>)}}
父组件调用子组件是传入 JSX
class App extends Component {render () {return (<View className='container'><DialogrenderHeader={<View className='welcome-message'>Welcome!</View>}renderFooter={<Button className='close'>Close</Button>}><View className="dialog-message">Thank you for using Taro.</View></Dialog></View>)}}
组件属性传递注意
不要以 id、class、style 作为自定义组件的属性与内部 state 的名称,因为这些属性名在微信小程序小程序中会丢失。
组件 state 与 props 里字段重名的问题
不要在 state 与 props 上用同名的字段,因为这些字段在微信小程序中都会挂在 data 上。
小程序中页面生命周期 componentWillMount 不一致问题
由于微信小程序里页面在 onLoad 时才能拿到页面的路由参数,而页面 onLoad 前组件都已经 attached 了。因此页面的 componentWillMount 可能会与预期不太一致。例如:
// 错误写法render () {// 在 willMount 之前无法拿到路由参数const abc = this.$router.params.abcreturn <Custom adc={abc} />}// 正确写法componentWillMount () {const abc = this.$router.params.abcthis.setState({abc})}render () {// 增加一个兼容判断return this.state.abc && <Custom adc={abc} />}
对于不需要等到页面 willMount 之后取路由参数的页面则没有任何影响。
JS 编码必须用单引号
在 Taro 中,JS 代码里必须书写单引号,特别是 JSX 中,如果出现双引号,可能会导致编译错误。
环境变量 process.env 的使用
不要以解构的方式来获取通过 env 配置的 process.env 环境变量,请直接以完整书写的方式 process.env.NODE_ENV 来进行使用
// 错误写法,不支持const { NODE_ENV = 'development' } = process.envif (NODE_ENV === 'development') {...}// 正确写法if (process.env.NODE_ENV === 'development') {}
自定义组件样式不能写在外部
微信小程序的自定义组件样式默认是不能受外部样式影响的,例如在页面中引用了一个自定义组件,在页面样式中直接写自定义组件元素的样式是无法生效的。这一点,在 Taro 中也是一样,而这也是与大家认知的传统 Web 开发不太一样。
补充:
页面结构比较复杂使用CustomWrapper优化性能
import { View, Text, CustomWrapper } from '@tarojs/components'export default function () {return (<View className='index'><Text>Demo</Text><CustomWrapper><GoodsList /></CustomWrapper></View>)}
多个包含ifrmae的页面跳转,需要清除iframe
主要是taro跳转页面的时候,还会保留上一个页面的dom元素,只是display为none了,iframe不清除,会多一层历史记录。
使用scrollview自带的滚动
错误写法:
matchMedia代替手动判断
//bad{height>=400 && orientation==='landscape' && <View>...}//good<MatchMedia minHeight="400" orientation="landscape"><view>当页面高度不小于 400 px 且屏幕方向为纵向时展示这里</view></MatchMedia>
数据量较大时,使用跳转预加载
// A 页面// 调用跳转方法前使用 Taro.preloadTaro.preload(fetchSomething())Taro.navigateTo({ url: '/pages/B/B' })// B 页面componentWillMount () {console.log(Taro.getCurrentInstance().preloadData)}
taro3.1之前版本,删除楼层节点需要隔离
//bad<View><!-- 轮播 --><Slider /><!-- 商品组 --><Goods /><!-- 模态弹窗 -->{isShowModal && <Modal />}</View>//good<View><!-- 轮播 --><Slider /><!-- 商品组 --><Goods /><!-- 模态弹窗 --><View>{isShowModal && <Modal />}</View></View>
基础组件的属性要保持引用
//bad<Maplatitude={22.53332}longitude={113.93041}markers={[{latitude: 22.53332,longitude: 113.93041}]}/>//good<Maplatitude={22.53332}longitude={113.93041}markers={this.state.markers}/>
基础组件不要设置非标准的属性
//bad<Text something='extra' />
滑动蒙层、弹窗等覆盖式元素防止滚动穿透
解决办法:
1) 使用样式解决(推荐)
给需要禁用滚动的组件写一个样式,类似于:
{overflow:hidden;height: 100vh;}
2) catchMove
对于 Map 等极个别组件,使用样式固定宽高也无法阻止滚动,因为这些组件本身就具有滚动的能力。所以第一种办法处理不了冒泡到 Map 组件上的滚动事件。
这时候可以为 View 组件增加 catchMove 属性:
// 这个 View 组件会绑定 catchtouchmove 事件而不是 bindtouchmove<View catchMove />
不要频繁调用Taro.getCurrentInstance() ,将结果保存下来
class Index extends React.Component {inst = Taro.getCurrentInstance()componentDidMount () {console.log(this.inst)}}
