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 元素的裏面填充其它複雜的邏輯。

相關文章
相關標籤/搜索