Taro官网文档总结

最近一直在学习taro,网上搜的重点知识总结不多,因此想着本身写一篇我以为比较重要的知识点总结一下。css

1.文件组织形式

如下文件组织规范为最佳实践的建议html

全部项目源代码请放在项目根目录 src 目录下,项目所需最基本的文件包括 入口文件 以及 页面文件react

  • 入口文件为 app.js
  • 页面文件建议放置在 src/pages 目录下

一个可靠的 Taro 项目能够按照以下方式进行组织json

├── config                 配置目录
|   ├── dev.js             开发时配置
|   ├── index.js           默认配置
|   └── prod.js            打包时配置
├── src                    源码目录
|   ├── components         公共组件目录
|   ├── pages              页面文件目录
|   |   ├── index          index 页面目录
|   |   |   ├── banner     页面 index 私有组件
|   |   |   ├── index.js   index 页面逻辑
|   |   |   └── index.css  index 页面样式
|   ├── utils              公共方法库
|   ├── app.css            项目总通用样式
|   └── app.js             项目入口文件
└── package.json复制代码

2.文件命名

Taro 中普通 JS/TS 文件以小写字母命名,多个单词如下划线链接,例如 util.jsutil_helper.js小程序

Taro 组件文件命名遵循 Pascal 命名法,例如 ReservationCard.jsx微信小程序

3.JavaScript 书写规范

taro的书写规范大概和Eslint的规范相似,具体可参考官网连接:taro-docs.jd.com/taro/docs/s…数组

4.书写顺序

在 Taro 组件中会包含类静态属性、类属性、生命周期等的类成员,其书写顺序最好遵循如下约定(顺序从上至下)bash

  1. static 静态方法
  2. constructor
  3. componentWillMount
  4. componentDidMount
  5. componentWillReceiveProps
  6. shouldComponentUpdate
  7. componentWillUpdate
  8. componentDidUpdate
  9. componentWillUnmount
  10. 点击回调或者事件回调 好比 onClickSubmit() 或者 onChangeDescription()
  11. render

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 (
      <View className='test'>
        {isEnable && <Text className='test_text'>{myTime}</Text>}
      </View>
    )
  }
}复制代码

6.不要在调用 this.setState 时使用 this.state

因为 this.setState 异步的缘故,这样的作法会致使一些错误,能够经过给 this.setState 传入函数来避免微信

this.setState({
  value: this.state.value + 1
})   // ✗ 错误


this.setState(prevState => ({ value: prevState.value + 1 }))    // ✓ 正确复制代码

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

list.map(item => {
  return (
    <View className='list_item' key={item.id}>{item.name}</View>
  )
})复制代码

8.尽可能避免在 componentDidMount 中调用 this.setState

由于在 componentDidMount 中调用 this.setState 会致使触发更新app

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 (
      <View className='test'>
        {isEnable && <Text className='test_text'>{myTime}</Text>}
      </View>
    )
  }
}
复制代码

不要在 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 (
      <View className='test'>
        {isEnable && <Text className='test_text'>{myTime}</Text>}
      </View>
    )
  }
}复制代码

9.事件绑定均以 on 开头

在 Taro 中全部默认事件如 onClickonTouchStart 等等,均以 on 开头

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

class MyComponent extends Component {
  state = {
    myTime: 12
  }

  clickHandler (e) {
    console.log(e)
  }
  
  render () {
    const { myTime } = this.state

    return (
      <View className='test' onClick={this.clickHandler}>    // ✓ 正确
        <Text className='test_text'>{myTime}</Text>
      </View>
    )
  }
}复制代码

10.不能使用 Array#map 以外的方法操做 JSX 数组

Taro 在小程序端实际上把 JSX 转换成了字符串模板,而一个原生 JSX 表达式其实是一个 React/Nerv 元素(react-element)的构造器,所以在原生 JSX 中你能够随意地对一组 React 元素进行操做。但在 Taro 中你只能使用 map 方法,Taro 转换成小程序中 wx:for

11.设计稿及尺寸单位

在 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

12.组件化 & Props

组件能够将 UI 切分红一些的独立的、可复用的部件,这样你就只需专一于构建每个单独的部件。

组件从概念上看就像是函数,它能够接收任意的输入值(称之为 props),并返回一个须要在页面上展现的 Taro 元素。

Props 的只读性

一个声明的组件决不能修改它本身的 props

使用 PropTypes 检查类型

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

import PropTypes from 'prop-types';

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

Greeting.propTypes = {
  name: PropTypes.string
};复制代码

13.正确地使用 State

关于 setState() 这里有三件事情须要知道:

1.不要直接更新状态

例如,此代码不会从新渲染组件:

// Wrong
this.state.comment = 'Hello'
复制代码

应当使用 setState():

// Correct
this.setState({ comment: 'Hello' })复制代码

2.状态更新必定是异步的

Taro 能够将多个 setState() 调用合并成一个调用来提升性能。

由于 this.stateprops 必定是异步更新的,因此你不能在 setState 立刻拿到 state 的值,例如:

// 假设咱们以前设置了 this.state.counter = 0
updateCounter () {
  this.setState({
    counter: 1
  })
  console.log(this.state.counter) // 这里 counter 仍是 0
}
复制代码

正确的作法是这样,在 setState 的第二个参数传入一个 callback:

// 假设咱们以前设置了 this.state.counter = 0
updateCounter () {
  this.setState({
    counter: 1
  }, () => {
    // 在这个函数内你能够拿到 setState 以后的值
  })
}复制代码

3.state 更新会被合并

当你调用 setState(),Taro 将合并你提供的对象到当前的状态中。

例如,你的状态可能包含几个独立的变量:

constructor(props) {
  super(props)
  this.state = {
    posts: [],
    comments: []
  }
}
复制代码

而后经过调用独立的 setState() 调用分别更新它们:

componentDidMount() {
  fetchPosts().then(response => {
    this.setState({
      posts: response.posts
    });
  });

  fetchComments().then(response => {
    this.setState({
      comments: response.comments
    })
  })
}
复制代码

合并是浅合并,因此 this.setState({comments}) 不会改变 this.state.posts 的值,但会彻底替换 this.state.comments 的值。

14.条件渲染

枚举条件渲染

有时渲染的条件很是多,不论是 if-else 仍是 switch-case 来作条件渲染都会显得太麻烦。这时咱们可使用「表驱动法」:枚举渲染。

function Loading (props) {
  const { loadingText, LOADING_STATUS, loadingStatus, onRetry } = props
  return (
    <View className='loading-status'>
      {
        {
          'loading': loadingText,
          'fail': <View onClick={onRetry}> 加载失败, 点击重试 </View>,
          'no-more': '没有更多了'
        }[loadingStatus] /** loadingStatus 是 `loading`、`fail`、`no-more`  其中一种状态 **/
      }
    </View>
  )
}复制代码

15.渲染多个组件

下面,咱们使用 JavaScript 中的 map() 方法遍历 numbers 数组。对数组中的每一个元素返回 <Text> 标签,最后咱们获得一个数组 listItems

const numbers = [...Array(100).keys()] // [0, 1, 2, ..., 98, 99]
const listItems = numbers.map((number) => {
  return <Text className='li'> 我是第 {number + 1} 个数字</Text>
})
复制代码

这段代码生成了一个 1 到 100 的数字列表。

Keys

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

taroKeys

taroKey 适用于循环渲染原生小程序组件,赋予每一个元素惟一肯定标识,转换为小程序的 wx:key

元素的 key 在他的兄弟元素之间应该惟一

数组元素中使用的 key 在其兄弟之间应该是独一无二的。然而,它们不须要是全局惟一的。当咱们生成两个不一样的数组时,咱们可使用相同的 key

16.类函数式组件

v1.3.0-beta.0 起支持

因为一个文件不能定义两个组件,但有时候咱们须要组件内部的抽象组件,这时类函数式组件就是你想要答案。假设咱们有一个 Class 组件,它包括了一个 Header 一个 Footer,咱们能够这样定义:

class SomePage extends Taro.Component {
  renderHeader () {
    const { header } = this.state
    return <View>{header}</View>
  }

  renderFooter (footer) {
    return <View>{footer}</View>
  }

  render () {
    return (
      <View>
        {this.renderHeader()}
        {...}
        {this.renderFooter('footer')}
      </View>
    )
  }
}
复制代码

renderHeaderrenderFooter 函数中,咱们能够访问类的 this,也能够传入不限量的参数,这类型的函数也能够调用无限次数。但这样的写法也存在一些限制:

  1. 函数的命名必须以 render 开头,render 后的第一个字母须要大写
  2. 函数的参数不得传入 JSX 元素或 JSX 元素引用
  3. 函数不能递归地调用自身

17.在咱们设计组件时,有些组件一般不知道本身的子组件会有什么内容,例如 SidebarDialog 这样的容器组件。

咱们建议在这样的状况使用 this.props.children 来传递子元素:

class Dialog extends Component {
  render () {
    return (
      <View className='dialog'>
        <View className='header'>Welcome!</View>
        <View className='body'>
          {this.props.children}
        </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)都会传递到它的组件。

请不要对 this.props.children 进行任何操做。Taro 在小程序中实现这个功能使用的是小程序的 slot 功能,也就是说你能够把 this.props.children 理解为 slot 的语法糖,this.props.children 在 Taro 中并非 React 的 ReactElement 对象,所以形如 this.props.children && this.props.childrenthis.props.children[0] 在 Taro 中都是非法的。

this.props.children 没法用 defaultProps 设置默认内容。因为小程序的限制,Taro 也没法知道组件的消费者是否传入内容,因此没法应用默认内容。

不能把 this.props.children 分解为变量再使用。因为普通的 props 有一个确切的值,因此当你把它们分解为变量运行时能够处理,this.props.children 则不能这样操做,你必须显性地把 this.props.children 所有都写完整才能实现它的功能。

组合

1.1.9 开始支持

有些状况你不只仅须要只传递一个子组件,可能会须要不少个「占位符」。例如在这个 Dialog 组件中,你不只须要自定义它的 body,你但愿它的 headerfooter 都是给 Dialog 组件的使用者自由定制。这种状况能够这样作:

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>
    )
  }
}

class App extends Component {
  render () {
    return (
      <View className='container'>
        <Dialog
          renderHeader={
            <View className='welcome-message'>Welcome!</View>
          }
          renderFooter={
            <Button className='close'>Close</Button>
          }
        >
          <View className="dialog-message">
            Thank you for using Taro.
          </View>
        </Dialog>
      </View>
    )
  }
}
复制代码

在咱们声明 Dialog 组件时,headerfooter 部分咱们分别增长了 this.props.renderHeaderthis.props.renderFooter 做为占位符。相应地,咱们在使用 Dialog 组件时,就能够给 renderHeaderrenderFooter 传入 JSX 元素,这两个分别传入的 JSX 元素将会填充它们在 Dialog 组件中的位置——就像在 Dialog JSX 标签里写入的内容,会填充到 this.props.children 的位置同样。

注意事项

组件的组合须要遵照 this.props.children 的全部规则。组合这个功能和 this.props.children 同样是经过 slot 实现的,也就是说 this.props.children 的限制对于组件组合也都一样适用。

全部组合都必须用 render 开头,且遵照驼峰式命名法。和咱们的事件规范以 on 开头同样,组件组合使用 render 开头。

组合只能传入单个 JSX 元素,不能传入其它任何类型。当你须要进行一些条件判断或复杂逻辑操做的时候,可使用一个 Block 元素包裹住,而后在 Block 元素的里面填充其它复杂的逻辑。

相关文章
相关标签/搜索