1.不要使用 eval()
2.
禁止使用 Object 构造器
let config = new Object() // ✗ 错误
3.
不使用 Generator 函数语法
使用 Promise 或者 async functions 来实现异步编程
function* helloWorldGenerator() { // ✗ 错误
yield 'hello';
yield 'world';
return 'ending';
}
4.
SX 属性均使用单引号
import Taro, { Component } from '@tarojs/taro'
import { View, Input } from '@tarojs/components'
class MyComponent extends Component {
render () {
return (
// ✓ 正确
12 // ✗ 错误
)
}
}
5.
推荐使用对象解构的方式来使用 state、props
import Taro, { Component } from '@tarojs/taro'
import { View, Input } from '@tarojs/components'
class MyComponent extends Component {
state = {
myTime: 12
}
render () {
const { isEnable } = this.props // ✓ 正确
const { myTime } = this.state // ✓ 正确
return (
{isEnable && {myTime}}
)
}
}
6.
不要以 class/id/style 作为自定义组件的属性名
// ✗ 错误
// ✗ 错误
// ✗ 错误
7.
不要在调用 this.setState 时使用 this.state
由于 this.setState 异步的缘故,这样的做法会导致一些错误,可以通过给 this.setState 传入函数来避免
this.setState({
value: this.state.value + 1
}) // ✗ 错误
this.setState(prevState => ({ value: prevState.value + 1 })) // ✓ 正确
8.
map 循环时请给元素加上 key 属性
list.map(item => {
return (
{item.name}
)
})
9.
尽量避免在 componentDidMount 中调用 this.setState
因为在 componentDidMount 中调用 this.setState 会导致触发更新
import Taro, { Component } from '@tarojs/taro'
import { View, Input } from '@tarojs/components'
class MyComponent extends Component {
state = {
myTime: 12
}
componentDidMount () {
this.setState({ // ✗ 尽量避免,可以在 componentWillMount 中处理
name: 1
})
}
render () {
const { isEnable } = this.props
const { myTime } = this.state
return (
{isEnable && {myTime}}
)
}
}
10.
不要在 componentWillUpdate/componentDidUpdate/render 中调用 this.setState
import Taro, { Component } from '@tarojs/taro'
import { View, Input } from '@tarojs/components'
class MyComponent extends Component {
state = {
myTime: 12
}
componentWillUpdate () {
this.setState({ // ✗ 错误
name: 1
})
}
componentDidUpdate () {
this.setState({ // ✗ 错误
name: 1
})
}
render () {
const { isEnable } = this.props
const { myTime } = this.state
this.setState({ // ✗ 错误
name: 11
})
return (
{isEnable && {myTime}}
)
}
}
不要定义没有用到的 state
11.
组件最好定义 defaultProps
import Taro, { Component } from '@tarojs/taro'
import { View, Input } from '@tarojs/components'
class MyComponent extends Component {
static defaultProps = {
isEnable: true
}
state = {
myTime: 12
}
render () {
const { isEnable } = this.props
const { myTime } = this.state
return (
{isEnable && {myTime}}
)
}
}
12.taro注意:
不能在包含 JSX 元素的 map 循环中使用 if 表达式
以下代码会被 ESLint 提示警告,同时在 Taro(小程序端)也不会有效:
numbers.map((number) => {
let element = null
const isOdd = number % 2
if (isOdd) {
element =
}
return element
})
以下代码不会被警告,也应当在 Taro 任意端中能够运行:
numbers.map((number) => {
let isOdd = false
if (number % 2) {
isOdd = true
}
return isOdd &&
})
13.
尽量在 map 循环中使用条件表达式或逻辑表达式
numbers.map((number) => {
const isOdd = number % 2
return isOdd ? : null
})
numbers.map((number) => {
const isOdd = number % 2
return isOdd &&
})
14不能使用 Array#map 之外的方法操作 JSX 数组
15.
先处理好需要遍历的数组,然后再用处理好的数组调用 map 方法。
numbers.filter(isOdd).map((number) => )
for (let index = 0; index < array.length; index++) {
// do you thing with array
}
const element = array.map(item => {
return
})
16.
不能在 JSX 参数中使用匿名函数
以下代码会被 ESLint 提示警告,同时在 Taro(小程序端)也不会有效:
this.handleClick()} />
this.handleClick(e)} />
({})} />
17.
以下代码不会被警告,也应当在 Taro 任意端中能够运行:
18
不能在 JSX 参数中使用对象展开符
以下代码会被 ESLint 提示警告,同时在 Taro(小程序端)也不会有效:
19
不支持无状态组件
以下代码会被 ESLint 提示警告,同时在 Taro(小程序端)也不会有效:
function Test () {
return
}
function Test (ary) {
return ary.map(() => )
}
const Test = () => {
return
}
const Test = function () {
return
}
20
微信小程序中 onLaunch 通常带有一个参数 options,在 Taro 中你可以在所有生命周期和普通事件方法中通过 this.$router.params 访问到,在其他端也适用
21 render中不要写逻辑
22.
路由传参
我们可以通过在所有跳转的 url 后面添加查询字符串参数进行跳转传参,例如
// 传入参数 id=2&type=test
Taro.navigateTo({
url: '/pages/page/path/name?id=2&type=test'
})
这样的话,在跳转成功的目标页的生命周期方法里就能通过 this.$router.params 获取到传入的参数,例如上述跳转,在目标页的 componentWillMount 生命周期里获取入参
class C extends Taro.Component {
componentWillMount () {
console.log(this.$router.params) // 输出 { id: 2, type: 'test' }
}
}
23
在 Taro 中尺寸单位建议使用 px、 百分比 %,Taro 默认会对所有单位进行转换。在 Taro 中书写尺寸按照 1:1 的关系来进行书写,即从设计稿上量的长度 100px,那么尺寸书写就是 100px,当转成微信小程序的时候,尺寸将默认转换为 100rpx,当转成 H5 时将默认转换为以 rem 为单位的值。
如果你希望部分 px 单位不被转换成 rpx 或者 rem ,最简单的做法就是在 px 单位中增加一个大写字母,例如 Px 或者 PX 这样,则会被转换插件忽略。
结合过往的开发经验,Taro 默认以 750px 作为换算尺寸标准,如果设计稿不是以 750px 为标准,则需要在项目配置 config/index.js 中进行设置,例如设计稿尺寸是 640px,则需要修改项目配置 config/index.js 中的 designWidth配置为 640:
const config = {
projectName: 'myProject',
date: '2018-4-18',
designWidth: 640,
....
}
目前 Taro 支持 750、 640 、 828 三种尺寸设计稿,他们的换算规则如下:
const DEVICE_RATIO = {
'640': 2.34 / 2,
'750': 1,
'828': 1.81 / 2
}
24.
小程序样式中引用本地资源
在小程序的样式中,默认不能直接引用本地资源,只能通过网络地址、Base64 的方式来进行资源引用,为了方便开发,Taro 提供了直接在样式文件中引用本地资源的方式,其原理是通过 PostCSS 的 postcss-url 插件将样式中本地资源引用转换成 Base64 格式,从而能正常加载。
Taro 默认会对 10kb 大小以下的资源进行转换,如果需要修改配置,可以在 config/index.js 中进行修改,配置位于 weapp.module.postcss。
具体配置如下
// 小程序端样式引用本地资源内联
url: {
enable: true,
config: {
limit: 10240 // 设定转换尺寸上限
}
}
25
JavaScript 表达式也可以嵌套:
render () {
const todos = ['finish doc', 'submit pr', 'nag dan to review'];
return (
{todos.map((todo) => {todo})}
)
}
26 条件判断
{showHeader && }
27
使用 PropTypes 检查类型
随着应用日渐庞大,你可以通过类型检查捕获大量错误。要检查组件的属性,你需要配置特殊的 propTypes 属性:
import PropTypes from 'prop-types';
class Greeting extends Component {
render() {
return (
);
}
}
Greeting.propTypes = {
name: PropTypes.string
};
如上例,Taro 与 React 一样,也支持PropTypes 检查类型,目前在小程序端还有些问题,但在 H5 端可以使用,用法和在 React 里一样。 更多可参照React 的相关文档。
28
setState异步
// 假设我们之前设置了 this.state.counter = 0
updateCounter () {
this.setState({
counter: 1
}, () => {
// 在这个函数内你可以拿到 setState 之后的值
})
}
29
在 Taro 中另一个不同是你不能使用 catchEvent 的方式阻止事件冒泡。你必须明确的使用 stopPropagation。例如,阻止事件冒泡你可以这样写:
class Toggle extends React.Component {
constructor (props) {
super(props)
this.state = {isToggleOn: true}
}
onClick = (e) => {
e.stopPropagation()
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}))
}
render () {
return (
{this.state.isToggleOn ? 'ON' : 'OFF'}
)
}
}
30
向事件处理程序传递参数
通常我们会为事件处理程序传递额外的参数。例如,若是 id 是你要删除那一行的 id,以下两种方式都可以向事件处理程序传递参数:
Delete Row
31
当你通过 bind 方式向监听函数传参,在类组件中定义的监听函数,事件对象 e 要排在所传递参数的后面。
class Popper extends Component {
constructor () {
super(...arguments)
this.state = { name:'Hello world!' }
}
// 你可以通过 bind 传入多个参数
preventPop (name, test, e) { //事件对象 e 要放在最后
e.preventDefault()
}
render () {
return
}
}
32
父组件控制状态值来决定子组件的条件渲染
33
Keys
但是在上面的代码,你会得到一个报错:提醒你当循环一个数组时应该提供 keys。Keys 可以在 DOM 中的某些元素被增加或删除的时候帮助 Nerv/小程序 识别哪些元素发生了变化。因此你应当给数组中的每一个元素赋予一个确定的标识。
const numbers = [...Array(100).keys()] // [0, 1, 2, ..., 98, 99]
const listItems = numbers.map((number) => {
return
key={String(number)}
class='li'
>
我是第 {number + 1} 个数字
})
34不同数组中可以使用相同的key
数组元素中使用的 key 在其兄弟之间应该是独一无二的。然而,它们不需要是全局唯一的。当我们生成两个不同的数组时,我们可以使用相同的 key:
class App extends Componenet {
state = {
posts: [
{id: 1, title: 'Hello World', content: 'Welcome to learning Taro!'},
{id: 2, title: 'Installation', content: 'You can install Taro from npm.'}
]
}
render () {
const { posts } = this.state
const sidebar = (
{posts.map((post) =>
{post.title}
)}
)
const content = posts.map((post) => {
return
{post.title}
{post.content}
})
return (
{sidebar}
{content}
)
}
}
35
Children
在我们设计组件时,有些组件通常不知道自己的子组件会有什么内容,例如 Sidebar 和 Dialog 这样的容器组件。
我们建议在这样的情况使用 this.props.children 来传递子元素:
class Dialog extends Component {
render () {
return (
Welcome!
{this.props.children}
-- divider --
)
}
}
这样就能允许其它组件在 JSX 中嵌套任意子组件传递给 Dialog:
class App extends Component {
render () {
return (
Thank you for using Taro.
)
}
}
在 JSX 标签内的任何内容都会作为它的子元素(Children)都会传递到它的组件。
36 refs rechart 元素绑定初始化
class MyComponent extends Component { componentDidMount () { // 如果 ref 的是小程序原生组件,那只有在 didMount 生命周期之后才能通过 // this.refs.input 访问到小程序原生组件 if (process.env.TARO_ENV === 'weapp') { // 这里 this.refs.input 访问的时候通过 `wx.createSeletorQuery` 取到的小程序原生组件 } else if (process.env.TARO_ENV === 'h5') { // 这里 this.refs.input 访问到的是 `@tarojs/components` 的 `Input` 组件实例 } } render () { return } }
37
利用 externalClasses 定义段定义若干个外部样式类。这个特性从小程序基础库版本 1.9.90 开始支持。
/* CustomComp.js */
export default CustomComp extends Component {
static externalClasses = ['my-class']
render () {
return 这段文本的颜色由组件外的 class 决定
}
}/* MyPage.js */
export default MyPage extends Component {
render () {
return
}
}/* MyPage.scss */
.red-text {
color: red;
}
38
全局样式类
使用外部样式类可以让组件使用指定的组件外样式类,如果希望组件外样式类能够完全影响组件内部,可以将组件构造器中的 options.addGlobalClass 字段置为 true。这个特性从小程序基础库版本 2.2.3 开始支持。
/* CustomComp.js */
export default CustomComp extends Component {
static options = {
addGlobalClass: true
}
render () {
return 这段文本的颜色由组件外的 class 决定
}
}/* 组件外的样式定义 */
.red-text {
color: red;
}
39
使用 this.$componentType 来判断当前 Taro.Component 是页面还是组件
40
this.$componentType 可能取值分别为 PAGE 和 COMPONENT,开发者可以根据此变量的取值分别采取不同逻辑。
41
在微信小程序中,从调用 Taro.navigateTo、Taro.redirectTo 或 Taro.switchTab 后,到页面触发 componentWillMount 会有一定延时。因此一些网络请求可以提前到发起跳转前一刻去请求。
Taro 提供了 componentWillPreload 钩子,它接收页面跳转的参数作为参数。可以把需要预加载的内容通过 return 返回,然后在页面触发 componentWillMount 后即可通过 this.$preloadData 获取到预加载的内容。
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
...
}
}
42
预加载
在微信小程序中,从调用 Taro.navigateTo、Taro.redirectTo 或 Taro.switchTab 后,到页面触发 componentWillMount 会有一定延时。因此一些网络请求可以提前到发起跳转前一刻去请求。
Taro 提供了 componentWillPreload 钩子,它接收页面跳转的参数作为参数。可以把需要预加载的内容通过 return 返回,然后在页面触发 componentWillMount 后即可通过 this.$preloadData 获取到预加载的内容。
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
...
}
}
43 全局变量
全局变量
在 Taro 中推荐使用 Redux 来进行全局变量的管理,但是对于一些小型的应用, Redux 就可能显得比较重了,这时候如果想使用全局变量,推荐如下使用。
新增一个自行命名的 JS 文件,例如 global_data.js,示例代码如下
const globalData = {}
export function set (key, val) {
globalData[key] = val
}
export function get (key) {
return globalData[key]
}
随后就可以在任意位置进行使用啦
import { set as setGlobalData, get as getGlobalData } from './path/name/global_data'
setGlobalData('test', 1)
getGlobalData('test')
44 上传下载
上传、下载
Taro.uploadFile(OBJECT)
使用方式同 wx.uploadFile,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
const uploadTask = Taro.uploadFile(params).then(...)
Taro.downloadFile(OBJECT)
使用方式同 wx.downloadFile,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.downloadFile(params).then(...)
45 端能力api
图片
Taro.chooseImage(OBJECT)
使用方式同 wx.chooseImage,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.chooseImage(params).then(...)
Taro.previewImage(OBJECT)
使用方式同 wx.previewImage,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.previewImage(params).then(...)
Taro.getImageInfo(OBJECT)
使用方式同 wx.getImageInfo,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.getImageInfo(params).then(...)
Taro.saveImageToPhotosAlbum(OBJECT)
示例代码:
import Taro from '@tarojs/taro'
Taro.saveImageToPhotosAlbum(params).then(...)
46 端能力api
Taro.showToast(OBJECT)
Taro.showToast({ title: '成功', icon: 'success', duration: 2000 }) .then(res => console.log(res))
Taro.showLoading(OBJECT)
显示 loading 提示框, 需主动调用 Taro.hideLoading 才能关闭提示框,支持 Promise 化使用。
OBJECT 参数说明:
参数类型必填说明
title
String
是
提示的内容
mask
Boolean
否
是否显示透明蒙层,防止触摸穿透,默认:false
success
Function
否
接口调用成功的回调函数
fail
Function
否
接口调用失败的回调函数
complete
Function
否
接口调用结束的回调函数(调用成功、失败都会执行)
示例代码:
import Taro from '@tarojs/taro'
Taro.showLoading({
title: 'loading'
})
.then(res => console.log(res))
Taro.hideToast()
隐藏消息提示框
Taro.hideLoading()
隐藏 loading 提示框
Taro.showModal(OBJECT)
import Taro from '@tarojs/taro' // 注意:无论用户点击确定还是取消,Promise 都会 resolve。 Taro.showModal({ title: 'xxx', content: 'hello world', }) .then(res => console.log(res.confirm, res.cancel))
Taro.showActionSheet(OBJECT)
显示操作菜单,支持 Promise 化使用。
设置导航条
Taro.setNavigationBarTitle(OBJECT)
示例代码:
import Taro from '@tarojs/taro'
Taro.setNavigationBarTitle(params).then(...)
Taro.showNavigationBarLoading()
在当前页面显示导航条加载动画。
Taro.hideNavigationBarLoading()
隐藏导航条加载动画。
Taro.setNavigationBarColor(OBJECT)
示例代码:
import Taro from '@tarojs/taro'
Taro.setNavigationBarColor(params).then(...)
API 支持度
API微信小程序H5ReactNative
Taro.setNavigationBarTitle
✔️
✔️
Taro.showNavigationBarLoading
✔️
✔️
Taro.hideNavigationBarLoading
✔️
✔️
Taro.setNavigationBarColor
✔️
✔️(不支持 animation 参数)
设置 tabBar
Taro.setTabBarBadge(OBJECT)
使用方式同 wx.setTabBarBadge,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.setTabBarBadge(params).then(...)
Taro.removeTabBarBadge(OBJECT)
示例代码:
import Taro from '@tarojs/taro'
Taro.removeTabBarBadge(params).then(...)
Taro.showTabBarRedDot(OBJECT)
使用方式同 wx.showTabBarRedDot,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.showTabBarRedDot(params).then(...)
Taro.hideTabBarRedDot(OBJECT)
使用方式同 wx.hideTabBarRedDot,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.hideTabBarRedDot(params).then(...)
Taro.setTabBarStyle(OBJECT)
使用方式同 wx.setTabBarStyle,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.setTabBarStyle(params).then(...)
Taro.setTabBarItem(OBJECT)
使用方式同 wx.setTabBarItem,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.setTabBarItem(params).then(...)
Taro.showTabBar(OBJECT)
使用方式同 wx.showTabBar,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.showTabBar(params).then(...)
Taro.hideTabBar(OBJECT)
使用方式同 wx.hideTabBar,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.hideTabBar(params).then(...)
API 支持度
API微信小程序H5ReactNative
Taro.setTabBarBadge
✔️
Taro.removeTabBarBadge
✔️
Taro.showTabBarRedDot
✔️
Taro.hideTabBarRedDot
✔️
Taro.setTabBarStyle
✔️
Taro.setTabBarItem
✔️
Taro.showTabBar
✔️
Taro.hideTabBar
✔️
设置置顶信息
Taro.setTopBarText(OBJECT)
使用方式同 wx.setTopBarText,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.setTopBarText(params).then(...)
API 支持度
API微信小程序H5ReactNative
Taro.setTopBarText
✔️
导航
Taro.navigateTo(OBJECT)
使用方式同 wx.navigateTo,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.navigateTo(params).then(...)
Taro.redirectTo(OBJECT)
使用方式同 wx.redirectTo,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.redirectTo(params).then(...)
Taro.switchTab(OBJECT)
使用方式同 wx.switchTab,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.switchTab(params).then(...)
Taro.navigateBack(OBJECT)
示例代码:
import Taro from '@tarojs/taro'
Taro.navigateBack({ delta: 2 })
Taro.reLaunch(OBJECT)
使用方式同 wx.reLaunch,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.reLaunch(params).then(...)
Taro.getCurrentPages(OBJECT)
使用方式同 getCurrentPages, 获取当前的页面栈,决定需要返回几层。
示例代码:
import Taro from '@tarojs/taro'
Taro.getCurrentPages().length
API 支持度
API微信小程序H5ReactNative
Taro.navigateTo
✔️
✔️
✔️
Taro.redirectTo
✔️
✔️
✔️
Taro.switchTab
✔️
✔️
Taro.navigateBack
✔️
✔️
✔️
Taro.reLaunch
✔️
✔️
Taro.getCurrentPages
✔️
✔️
动画
Taro.createAnimation(OBJECT)
示例代码:
import Taro from '@tarojs/taro'
const animation = Taro.createAnimation({
transformOrigin: "50% 50%",
duration: 1000,
timingFunction: "ease",
delay: 0
})
API 支持度
API微信小程序H5ReactNative
Taro.createAnimation
✔️
位置
Taro.pageScrollTo(OBJECT)
使用方式同 wx.pageScrollTo,支持 Promise 化使用。
示例代码:
import Taro from '@tarojs/taro'
Taro.pageScrollTo(params).then(...)
API 支持度
API微信小程序H5ReactNative
Taro.pageScrollTo
✔️
绘图
Taro.createCanvasContext(canvasId, this.$scope)
Taro.createContext(不推荐使用)
创建并返回绘图上下文。
Taro.drawCanvas(不推荐使用)
API 支持度
API微信小程序H5ReactNative
Taro.createCanvasContext
✔️
Taro.createContext
✔️
Taro.drawCanvas
✔️
下拉刷新
Taro.startPullDownRefresh(OBJECT)
示例代码:
import Taro from '@tarojs/taro'
Taro.startPullDownRefresh(params).then(...)
Taro.stopPullDownRefresh()
停止当前页面下拉刷新。
示例代码:
import Taro from '@tarojs/taro'
Taro.stopPullDownRefresh()