taro框架的缺陷以及注意事项

时间:2025-01-30 17:12:04

/p/9d3318f7f219

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 (
      <View className='test'>     // ✓ 正确
        <Text className="test_text">12</Text>     // ✗ 错误
      </View>
    )
  }
}

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 } =      // ✓ 正确
    const { myTime } =      // ✓ 正确
    return (
      <View className='test'>
        {isEnable && <Text className='test_text'>{myTime}</Text>}
      </View>
    )
  }
}

6.

不要以 class/id/style 作为自定义组件的属性名

<Hello class='foo' />     // ✗ 错误
<Hello id='foo' />     // ✗ 错误
<Hello style='foo' />     // ✗ 错误

7.

不要在调用 时使用

由于 异步的缘故,这样的做法会导致一些错误,可以通过给 传入函数来避免

({
  value:  + 1
})   // ✗ 错误


(prevState => ({ value:  + 1 }))    // ✓ 正确

8.

map 循环时请给元素加上 key 属性

(item => {
  return (
    <View className='list_item' key={}>{}</View>
  )
})

9.

尽量避免在 componentDidMount 中调用

因为在 componentDidMount 中调用  会导致触发更新

import Taro, { Component } from '@tarojs/taro'
import { View, Input } from '@tarojs/components'

class MyComponent extends Component {
  state = {
    myTime: 12
  }
  
  componentDidMount () {
    ({     // ✗ 尽量避免,可以在 componentWillMount 中处理
      name: 1
    })
  }
  
  render () {
    const { isEnable } = 
    const { myTime } = 
    return (
      <View className='test'>
        {isEnable && <Text className='test_text'>{myTime}</Text>}
      </View>
    )
  }
}

10.

不要在 componentWillUpdate/componentDidUpdate/render 中调用

import Taro, { Component } from '@tarojs/taro'
import { View, Input } from '@tarojs/components'

class MyComponent extends Component {
  state = {
    myTime: 12
  }
  
  componentWillUpdate () {
    ({     // ✗ 错误
      name: 1
    })
  }
  
  componentDidUpdate () {
    ({     // ✗ 错误
      name: 1
    })
  }
  
  render () {
    const { isEnable } = 
    const { myTime } = 
    ({     // ✗ 错误
      name: 11
    })
    return (
      <View className='test'>
        {isEnable && <Text className='test_text'>{myTime}</Text>}
      </View>
    )
  }
}

不要定义没有用到的 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 } = 
    const { myTime } = 

    return (
      <View className='test'>
        {isEnable && <Text className='test_text'>{myTime}</Text>}
      </View>
    )
  }
}

注意:

不能在包含 JSX 元素的 map 循环中使用 if 表达式

以下代码会被 ESLint 提示警告,同时在 Taro(小程序端)也不会有效:

((number) => {
  let element = null
  const isOdd = number % 2
  if (isOdd) {
    element = <Custom />
  }
  return element
})

以下代码不会被警告,也应当在 Taro 任意端中能够运行:

((number) => {
  let isOdd = false
  if (number % 2) {
    isOdd = true
  }
  return isOdd && <Custom />
})

 

13.

尽量在 map 循环中使用条件表达式或逻辑表达式

((number) => {
  const isOdd = number % 2
  return isOdd ? <Custom /> : null
})

((number) => {
  const isOdd = number % 2
  return isOdd && <Custom />
})

 

14不能使用 Array#map 之外的方法操作 JSX 数组

15.

先处理好需要遍历的数组,然后再用处理好的数组调用 map 方法。

(isOdd).map((number) => <View />)

for (let index = 0; index < ; index++) {
  // do you thing with array
}

const element = (item => {
  return <View />
})

 

16.

不能在 JSX 参数中使用匿名函数

以下代码会被 ESLint 提示警告,同时在 Taro(小程序端)也不会有效:

<View onClick={() => ()} />

<View onClick={(e) => (e)} />

<View onClick={() => ({})} />

<View onClick={function () {}} />

<View onClick={function (e) {(e)}} />

 

17.

以下代码不会被警告,也应当在 Taro 任意端中能够运行:

<View onClick={} />

<View onClick={} />

<View onClick={(this)} />

<View onClick={(this)} />

 

18

不能在 JSX 参数中使用对象展开符

以下代码会被 ESLint 提示警告,同时在 Taro(小程序端)也不会有效:

<View {...} />

<View {...props} />

<Custom {...props} />

 

19

不支持无状态组件

以下代码会被 ESLint 提示警告,同时在 Taro(小程序端)也不会有效:

function Test () {
  return <View />
}

function Test (ary) {
  return (() => <View />)
}

const Test = () => {
  return <View />
}

const Test = function () {
  return <View />
}

 

20

微信小程序中 onLaunch 通常带有一个参数 options,在 Taro 中你可以在所有生命周期和普通事件方法中通过 this.$ 访问到,在其他端也适用

21 render中不要写逻辑

22.

路由传参

我们可以通过在所有跳转的 url 后面添加查询字符串参数进行跳转传参,例如

// 传入参数 id=2&type=test
({
  url: '/pages/page/path/name?id=2&type=test'
})

这样的话,在跳转成功的目标页的生命周期方法里就能通过 this.$ 获取到传入的参数,例如上述跳转,在目标页的 componentWillMount 生命周期里获取入参

class C extends  {
  componentWillMount () {
    (this.$) // 输出 { 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/ 中进行设置,例如设计稿尺寸是 640px,则需要修改项目配置 config/ 中的 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/ 中进行修改,配置位于 

具体配置如下

// 小程序端样式引用本地资源内联
url: {
  enable: true,
  config: {
    limit: 10240 // 设定转换尺寸上限
  }
}

25

JavaScript 表达式也可以嵌套:

render () {
  const todos = ['finish doc', 'submit pr', 'nag dan to review'];
  return (
    <ul>
      {((todo) => <Text>{todo}</Text>)}
    </ul>
  )
}

26 条件判断

<View> {showHeader && <Header />} <Content /> </View> 

27

使用 PropTypes 检查类型

随着应用日渐庞大,你可以通过类型检查捕获大量错误。要检查组件的属性,你需要配置特殊的 propTypes 属性:

import PropTypes from 'prop-types';

class Greeting extends Component {
  render() {
    return (
      <h1>Hello, {}</h1>
    );
  }
}

 = {
  name: 
};

如上例,Taro 与 React 一样,也支持PropTypes 检查类型,目前在小程序端还有些问题,但在 H5 端可以使用,用法和在 React 里一样。 更多可参照React 的相关文档

28

setState异步

// 假设我们之前设置了  = 0
updateCounter () {
  ({
    counter: 1
  }, () => {
    // 在这个函数内你可以拿到 setState 之后的值
  })
}

 

 

29

在 Taro 中另一个不同是你不能使用 catchEvent 的方式阻止事件冒泡。你必须明确的使用 stopPropagation。例如,阻止事件冒泡你可以这样写:

class Toggle extends  {
  constructor (props) {
    super(props)
     = {isToggleOn: true}
  }

  onClick = (e) => {
    ()
    (prevState => ({
      isToggleOn: !
    }))
  }

  render () {
    return (
      <button onClick={}>
        { ? 'ON' : 'OFF'}
      </button>
    )
  }
}

30

向事件处理程序传递参数

通常我们会为事件处理程序传递额外的参数。例如,若是 id 是你要删除那一行的 id,以下两种方式都可以向事件处理程序传递参数:

<button onClick={(this, id)}>Delete Row</button>

31

当你通过 bind 方式向监听函数传参,在类组件中定义的监听函数,事件对象 e 要排在所传递参数的后面。

class Popper extends Component {
  constructor () {
    super(...arguments)
     = { name:'Hello world!' }
  }

  // 你可以通过 bind 传入多个参数
  preventPop (name, test, e) {    //事件对象 e 要放在最后
    ()
  }

  render () {
    return <Button onClick={(this, , 'test')}></Button>
  }
}

32

父组件控制状态值来决定子组件的条件渲染

33

Keys

但是在上面的代码,你会得到一个报错:提醒你当循环一个数组时应该提供 keys。Keys 可以在 DOM 中的某些元素被增加或删除的时候帮助 Nerv/小程序 识别哪些元素发生了变化。因此你应当给数组中的每一个元素赋予一个确定的标识。

const numbers = [...Array(100).keys()] // [0, 1, 2, ..., 98, 99]
const listItems = ((number) => {
  return <Text
    key={String(number)}
    class='li'
    >
    我是第 {number + 1} 个数字
  </Text>
})

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 } = 
    const sidebar = (
      <View>
        {((post) =>
          <Text key={}>
            {}
          </Text>
        )}
      </View>
    )
    const content = ((post) => {
      return <View key={}>
        <Text>{}</Text>
        <Text>{}</Text>
      </View>
    })
    return (
      <View>
        {sidebar}
        <View class="divider" />
        {content}
      </View>
    )
  }
}

35

Children

在我们设计组件时,有些组件通常不知道自己的子组件会有什么内容,例如 Sidebar 和 Dialog 这样的容器组件。

我们建议在这样的情况使用  来传递子元素:

class Dialog extends Component {
  render () {
    return (
      <View className='dialog'>
        <View className='header'>Welcome!</View>
        <View className='body'>
          {}
        </View>
        <View className='footer'>-- divider --</View>
      </View>
    )
  }
}

这样就能允许其它组件在 JSX 中嵌套任意子组件传递给 Dialog:

class App extends Component {
  render () {
    return (
      <View className='container'>
        <Dialog>
          <View className="dialog-message">
            Thank you for using Taro.
          </View>
        </Dialog>
      </View>
    )
  }
}

在 <Dialog /> JSX 标签内的任何内容都会作为它的子元素(Children)都会传递到它的组件。

36  refs   rechart 元素绑定初始化

class MyComponent extends Component { componentDidMount () { // 如果 ref 的是小程序原生组件,那只有在 didMount 生命周期之后才能通过 // 访问到小程序原生组件 if (.TARO_ENV === 'weapp') { // 这里 访问的时候通过 `` 取到的小程序原生组件 } else if (.TARO_ENV === 'h5') { // 这里 访问到的是 `@tarojs/components` 的 `Input` 组件实例 } } render () { return <Input ref='input' /> } } 

37

利用 externalClasses 定义段定义若干个外部样式类。这个特性从小程序基础库版本 1.9.90 开始支持。

/*  */
export default CustomComp extends Component {
  static externalClasses = ['my-class']

  render () {
    return <View className="my-class">这段文本的颜色由组件外的 class 决定</View>
  }
}
/*  */
export default MyPage extends Component {
  render () {
    return <CustomComp my-class="red-text" />
  }
}
/*  */
.red-text {
  color: red;
}

38

全局样式类

使用外部样式类可以让组件使用指定的组件外样式类,如果希望组件外样式类能够完全影响组件内部,可以将组件构造器中的  字段置为 true。这个特性从小程序基础库版本 2.2.3 开始支持。

/*  */
export default CustomComp extends Component {
  static options = {
    addGlobalClass: true
  }

  render () {
    return <View className="red-text">这段文本的颜色由组件外的 class 决定</View>
  }
}
/* 组件外的样式定义 */
.red-text {
  color: red;
}

 

39

使用 this.$componentType 来判断当前 是页面还是组件

40

this.$componentType 可能取值分别为 PAGE 和 COMPONENT,开发者可以根据此变量的取值分别采取不同逻辑。

 

41

微信小程序中,从调用  或  后,到页面触发 componentWillMount 会有一定延时。因此一些网络请求可以提前到发起跳转前一刻去请求。

Taro 提供了 componentWillPreload 钩子,它接收页面跳转的参数作为参数。可以把需要预加载的内容通过 return 返回,然后在页面触发 componentWillMount 后即可通过 this.$preloadData 获取到预加载的内容。

class Index extends Component {
  componentWillMount () {
    ('isFetching: ', )
    this.$preloadData
      .then(res => {
        ('res: ', res)
         = false
      })
  }

  componentWillPreload (params) {
    return ()
  }

  fetchData () {
     = true
    ...
  }
}

 

42

预加载

微信小程序中,从调用  或  后,到页面触发 componentWillMount 会有一定延时。因此一些网络请求可以提前到发起跳转前一刻去请求。

Taro 提供了 componentWillPreload 钩子,它接收页面跳转的参数作为参数。可以把需要预加载的内容通过 return 返回,然后在页面触发 componentWillMount 后即可通过 this.$preloadData 获取到预加载的内容。

class Index extends Component {
  componentWillMount () {
    ('isFetching: ', )
    this.$preloadData
      .then(res => {
        ('res: ', res)
         = false
      })
  }

  componentWillPreload (params) {
    return ()
  }

  fetchData () {
     = 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 上传下载

上传、下载

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

const uploadTask = (params).then(...)

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

 

45 端能力api

图片

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)
 
 

46 端能力api

(OBJECT)

({ title: '成功', icon: 'success', duration: 2000 }) .then(res => (res))

(OBJECT)

显示 loading 提示框, 需主动调用 才能关闭提示框,支持 Promise 化使用。

OBJECT 参数说明:

参数 类型 必填 说明
title String 提示的内容
mask Boolean 是否显示透明蒙层,防止触摸穿透,默认:false
success Function 接口调用成功的回调函数
fail Function 接口调用失败的回调函数
complete Function 接口调用结束的回调函数(调用成功、失败都会执行)

示例代码:

import Taro from '@tarojs/taro'

({
  title: 'loading'
})
  .then(res => (res))

()

隐藏消息提示框

()

隐藏 loading 提示框

(OBJECT)

import Taro from '@tarojs/taro' // 注意:无论用户点击确定还是取消,Promise 都会 resolve。 ({ title: 'xxx', content: 'hello world', }) .then(res => (, ))

 

(OBJECT)

显示操作菜单,支持 Promise 化使用。

 

设置导航条

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

()

在当前页面显示导航条加载动画。

()

隐藏导航条加载动画。

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

API 支持度

API 微信小程序 H5 ReactNative
✔️   ✔️
✔️   ✔️
✔️   ✔️
✔️   ✔️(不支持 animation 参数)

设置 tabBar

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

API 支持度

API 微信小程序 H5 ReactNative
✔️    
✔️    
✔️    
✔️    
✔️    
✔️    
✔️    
✔️    

设置置顶信息

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

API 支持度

API 微信小程序 H5 ReactNative
✔️    

导航

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

(OBJECT)

使用方式同 

示例代码:

import Taro from '@tarojs/taro'

({ delta: 2 })

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

(OBJECT)

使用方式同 getCurrentPages, 获取当前的页面栈,决定需要返回几层。

示例代码:

import Taro from '@tarojs/taro'

().length

API 支持度

API 微信小程序 H5 ReactNative
✔️ ✔️ ✔️
✔️ ✔️ ✔️
✔️   ✔️
✔️ ✔️ ✔️
✔️   ✔️  
✔️   ✔️

动画

(OBJECT)

使用方式同 

示例代码:

import Taro from '@tarojs/taro'

const animation = ({
  transformOrigin: "50% 50%",
  duration: 1000,
  timingFunction: "ease",
  delay: 0
})

API 支持度

API 微信小程序 H5 ReactNative
✔️    

位置

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

API 支持度

API 微信小程序 H5 ReactNative
✔️    

绘图

(canvasId, this.$scope)

使用方式同 

(不推荐使用)

创建并返回绘图上下文。

(不推荐使用)

使用方式同 

API 支持度

API 微信小程序 H5 ReactNative
✔️    
✔️    
✔️    

下拉刷新

(OBJECT)

使用方式同 ,支持 Promise 化使用。

示例代码:

import Taro from '@tarojs/taro'

(params).then(...)

()

停止当前页面下拉刷新。

示例代码:

import Taro from '@tarojs/taro'

()
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

相关文章