溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

taro和react有什么區(qū)別

發(fā)布時間:2020-11-16 10:38:14 來源:億速云 閱讀:409 作者:小新 欄目:web開發(fā)

這篇文章主要介紹了taro和react有什么區(qū)別,具有一定借鑒價值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

區(qū)別:1、Taro不支持在類方法中定義JSX,而react支持;2、Taro不能在包含JSX元素的map循環(huán)中使用if表達式,而react可以;3、Taro不能使用Array.map之外的方法操作JSX數(shù)組,而react可以。Taro 與 React 的差異(轉(zhuǎn)自小冊)

由于微信小程序的限制,React 中某些寫法和特性在 Taro 中還未能實現(xiàn),后續(xù)將會逐漸完善。 截止到本小冊發(fā)布前,Taro 的最新版本為 1.1,因此以下講解默認版本為 1.1。

暫不支持在 render() 之外的方法定義 JSX

由于微信小程序的 template 不能動態(tài)傳值和傳入函數(shù),Taro 暫時也沒辦法支持在類方法中定義 JSX。

無效情況

class App extends Component {
  _render() {
    return <View />
  }
}

class App extends Component {
  renderHeader(showHeader) {
    return showHeader && <Header />
  }
}

class App extends Component {
  renderHeader = (showHeader) => {
    return showHeader& & <Header />
  }
}

解決方案
在 render 方法中定義。

class App extends Component {

  render () {
    const { showHeader, showMain } = this.state
    const header = showHeader && <Header />
    const main = showMain && <Main />
    return (
      <View>
        {header}
        {main}
      </View>
    )
  }
}

不能在包含 JSX 元素的 map 循環(huán)中使用 if 表達式

無效情況

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

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

解決方案
盡量在 map 循環(huán)中使用條件表達式或邏輯表達式。

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

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

不能使用 Array.map 之外的方法操作 JSX 數(shù)組

Taro 在小程序端實際上把 JSX 轉(zhuǎn)換成了字符串模板,而一個原生 JSX 表達式實際上是一個 React/Nerv 元素(react - element)的構(gòu)造器,因此在原生 JSX 中你可以對任何一組 React 元素進行操作。但在 Taro 中你只能使用 map 方法,Taro 轉(zhuǎn)換成小程序中 wx:for。

無效情況

test.push(<View />)

numbers.forEach(numbers => {
  if (someCase) {
    a = <View />
  }
})

test.shift(<View />)

components.find(component => {
  return component === <View />
})

components.some(component => component.constructor.__proto__ === <View />.constructor)

numbers.filter(Boolean).map((number) => {
  const element = <View />
  return <View />
})

解決方案
先處理好需要遍歷的數(shù)組,然后再用處理好的數(shù)組調(diào)用 map 方法。

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

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

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

不能在 JSX 參數(shù)中使用匿名函數(shù)

無效情況

<View onClick={() => this.handleClick()} />

<View onClick={(e) => this.handleClick(e)} />

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

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

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

解決方案
使用 bind 或 類參數(shù)綁定函數(shù)。

<View onClick={this.props.hanldeClick.bind(this)} />

不能在 JSX 參數(shù)中使用對象展開符

微信小程序組件要求每一個傳入組件的參數(shù)都必須預(yù)先設(shè)定好,而對象展開符則是動態(tài)傳入不固定數(shù)量的參數(shù)。所以 Taro 沒有辦法支持該功能。

無效情況

<View {...this.props} />

<View {...props} />

<Custom {...props} />

解決方案
開發(fā)者自行賦值:

render () {
    const { id, title } = obj
    return <View id={id} title={title} />
}

不允許在 JSX 參數(shù)(props)中傳入 JSX 元素

由于微信小程序內(nèi)置的組件化的系統(tǒng)不能通過屬性(props) 傳函數(shù),而 props 傳遞函數(shù)可以說是 React 體系的根基之一,我們只能自己實現(xiàn)一套組件化系統(tǒng)。而自制的組件化系統(tǒng)不能使用內(nèi)置組件化的 slot 功能。兩權(quán)相害取其輕,我們暫時只能不支持該功能。

無效情況

<Custom child={<View />} />

<Custom child={() => <View />} />

<Custom child={function () { <View /> }} />

<Custom child={ary.map(a => <View />)} />

解決方案
通過 props 傳值在 JSX 模板中預(yù)先判定顯示內(nèi)容,或通過 props.children 來嵌套子組件。

不支持無狀態(tài)組件(Stateless Component)

由于微信的 template 能力有限,不支持動態(tài)傳值和函數(shù),Taro 暫時只支持一個文件只定義一個組件。為了避免開發(fā)者疑惑,暫時不支持定義 Stateless Component。

無效情況

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

解決方案
使用 class 定義組件。

class App extends Component {
  render () {
    return (
      <View />
    )
  }}

命名規(guī)范
Taro 函數(shù)命名使用駝峰命名法,如onClick,由于微信小程序的 WXML 不支持傳遞函數(shù),函數(shù)名編譯后會以字符串的形式綁定在 WXML 上,囿于 WXML 的限制,函數(shù)名有三項限制:

方法名不能含有數(shù)字
方法名不能以下劃線開頭或結(jié)尾
方法名的長度不能大于 20
請遵守以上規(guī)則,否則編譯后的代碼在微信小程序中會報以下錯誤:

taro和react有什么區(qū)別
推薦安裝 ESLint 編輯器插件
Taro 有些寫法跟 React 有些差異,可以通過安裝 ESLint 相關(guān)的編輯器插件來獲得人性化的提示。由于不同編輯器安裝的插件有所不同,具體安裝方法請自行搜索,這里不再贅述。 如下圖,就是安裝插件后獲得的提示:

taro和react有什么區(qū)別
taro和react有什么區(qū)別
最佳編碼方式
經(jīng)過較長時間的探索與驗證,目前 Taro 在微信小程序端是采用依托于小程序原生自定義組件系統(tǒng)來設(shè)計實現(xiàn) Taro 組件化的,所以目前小程序端的組件化會受到小程序原生組件系統(tǒng)的限制,而同時為了實現(xiàn)以 React 方式編寫代碼的目標,Taro 本身做了一些編譯時以及運行時的處理,這樣也帶來了一些值得注意的約束,所以有必要闡述一下 Taro 編碼上的最佳實踐。

組件樣式說明
微信小程序的自定義組件樣式默認是不能受外部樣式影響的,例如在頁面中引用了一個自定義組件,在頁面樣式中直接寫自定義組件元素的樣式是無法生效的。這一點,在 Taro 中也是一樣,而這也是與大家認知的傳統(tǒng) Web 開發(fā)不太一樣。

給組件設(shè)置 defaultProps
在微信小程序端的自定義組件中,只有在 properties 中指定的屬性,才能從父組件傳入并接收

Component({
  properties: {
    myProperty: { // 屬性名
      type: String, // 類型(必填),目前接受的類型包括:String, Number, Boolean, Object, Array, null(表示任意類型)
      value: '', // 屬性初始值(可選),如果未指定則會根據(jù)類型選擇一個
      observer: function (newVal, oldVal, changedPath) {
         // 屬性被改變時執(zhí)行的函數(shù)(可選),也可以寫成在 methods 段中定義的方法名字符串, 如:'_propertyChange'
         // 通常 newVal 就是新設(shè)置的數(shù)據(jù), oldVal 是舊數(shù)據(jù)
      }
    },
    myProperty2: String // 簡化的定義方式
  }
  ...
})

而在 Taro 中,對于在組件代碼中使用到的來自 props 的屬性,會在編譯時被識別并加入到編譯后的 properties 中,暫時支持到了以下寫法

this.props.property

const { property } = this.props

const property = this.props.property

但是一千個人心中有一千個哈姆雷特,不同人的代碼寫法肯定也不盡相同,所以 Taro 的編譯肯定不能覆蓋到所有的寫法,而同時可能會有某一屬性沒有使用而是直接傳遞給子組件的情況,這種情況是編譯時無論如何也處理不到的,這時候就需要大家在編碼時給組件設(shè)置 defaultProps 來解決了。

組件設(shè)置的 defaultProps 會在運行時用來彌補編譯時處理不到的情況,里面所有的屬性都會被設(shè)置到 properties 中初始化組件,正確設(shè)置 defaultProps 可以避免很多異常的情況的出現(xiàn)。

組件傳遞函數(shù)屬性名以 on 開頭
在 Taro 中,父組件要往子組件傳遞函數(shù),屬性名必須以 on 開頭

// 調(diào)用 Custom 組件,傳入 handleEvent 函數(shù),屬性名為 `onTrigger`
class Parent extends Component {

  handleEvent () {

  }

  render () {
    return (
      <Custom onTrigger={this.handleEvent}></Custom>
    )
  }
}

這是因為,微信小程序端組件化是不能直接傳遞函數(shù)類型給子組件的,在 Taro 中是借助組件的事件機制來實現(xiàn)這一特性,而小程序中傳入事件的時候?qū)傩悦麑懛?bindmyevent 或者 bind:myevent

<!-- 當自定義組件觸發(fā)“myevent”事件時,調(diào)用“onMyEvent”方法 -->
<component-tag-name bindmyevent="onMyEvent" />
<!-- 或者可以寫成 -->
<component-tag-name bind:myevent="onMyEvent" />

所以 Taro 中約定組件傳遞函數(shù)屬性名以 on 開頭,同時這也和內(nèi)置組件的事件綁定寫法保持一致了。

小程序端不要在組件中打印傳入的函數(shù)
前面已經(jīng)提到小程序端的組件傳入函數(shù)的原理,所以在小程序端不要在組件中打印傳入的函數(shù),因為拿不到結(jié)果,但是 this.props.onXxx && this.props.onXxx() 這種判斷函數(shù)是否傳入來進行調(diào)用的寫法是完全支持的。

小程序端不要將在模板中用到的數(shù)據(jù)設(shè)置為 undefined
由于小程序不支持將 data 中任何一項的 value 設(shè)為 undefined ,在 setState 的時候也請避免這么用。你可以使用 null 來替代。

小程序端不要在組件中打印 this.props.children
在微信小程序端是通過 來實現(xiàn)往自定義組件中傳入元素的,而 Taro 利用 this.props.children 在編譯時實現(xiàn)了這一功能, this.props.children 會直接被編譯成 標簽,所以它在小程序端屬于語法糖的存在,請不要在組件中打印它。

組件屬性傳遞注意
不要以 id、class、style 作為自定義組件的屬性與內(nèi)部 state 的名稱,因為這些屬性名在微信小程序中會丟失。

組件 state 與 props 里字段重名的問題
不要在 state 與 props 上用同名的字段,因為這些被字段在微信小程序中都會掛在 data 上。

小程序中頁面生命周期 componentWillMount 不一致問題
由于微信小程序里頁面在 onLoad 時才能拿到頁面的路由參數(shù),而頁面 onLoad 前組件都已經(jīng) attached 了。因此頁面的 componentWillMount 可能會與預(yù)期不太一致。例如:

// 錯誤寫法
render () {
  // 在 willMount 之前無法拿到路由參數(shù)
  const abc = this.$router.params.abc
  return <Custom adc={abc} />
}

// 正確寫法
componentWillMount () {
  const abc = this.$router.params.abc
  this.setState({
    abc
  })
}
render () {
  // 增加一個兼容判斷
  return this.state.abc && <Custom adc={abc} />
}

對于不需要等到頁面 willMount 之后取路由參數(shù)的頁面則沒有任何影響。

組件的 constructor 與 render 提前調(diào)用
很多細心的開發(fā)者應(yīng)該已經(jīng)注意到了,在 Taro 編譯到小程序端后,組件的 constructor 與 render 默認會多調(diào)用一次,表現(xiàn)得與 React 不太一致。

這是因為,Taro 的組件編譯后就是小程序的自定義組件,而小程序的自定義組件的初始化時是可以指定 data 來讓組件擁有初始化數(shù)據(jù)的。開發(fā)者一般會在組件的 constructor 中設(shè)置一些初始化的 state,同時也可能會在 render 中處理 state 與 props 產(chǎn)生新的數(shù)據(jù),在 Taro 中多出的這一次提前調(diào)用,就是為了收集組件的初始化數(shù)據(jù),給自定義組件提前生成 data ,以保證組件初始化時能帶有數(shù)據(jù),讓組件初次渲染正常。

所以,在編碼時,需要在處理數(shù)據(jù)的時候做一些容錯處理,這樣可以避免在 constructor 與 render 提前調(diào)用時出現(xiàn)由于沒有數(shù)據(jù)導(dǎo)致出錯的情況。

JS 編碼必須用單引號
在 Taro 中,JS 代碼里必須書寫單引號,特別是 JSX 中,如果出現(xiàn)雙引號,可能會導(dǎo)致編譯錯誤。

環(huán)境變量 process.env 的使用
不要以解構(gòu)的方式來獲取通過 env 配置的 process.env 環(huán)境變量,請直接以完整書寫的方式 process.env.NODE_ENV 來進行使用

// 錯誤寫法,不支持
const { NODE_ENV = 'development' } = process.env
if (NODE_ENV === 'development') {
  ...
}

// 正確寫法
if (process.env.NODE_ENV === 'development') {

}

預(yù)加載
在微信小程序中,從調(diào)用 Taro.navigateTo、Taro.redirectTo 或 Taro.switchTab 后,到頁面觸發(fā) componentWillMount 會有一定延時。因此一些網(wǎng)絡(luò)請求可以提前到發(fā)起跳轉(zhuǎn)前一刻去請求。

Taro 提供了 componentWillPreload 鉤子,它接收頁面跳轉(zhuǎn)的參數(shù)作為參數(shù)。可以把需要預(yù)加載的內(nèi)容通過 return 返回,然后在頁面觸發(fā) componentWillMount 后即可通過 this.$preloadData 獲取到預(yù)加載的內(nèi)容。

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

小結(jié)
由于 JSX 中的寫法千變?nèi)f化,我們不能支持到所有的 JSX 寫法,同時由于微信小程序端的限制,也有部分 JSX 的優(yōu)秀用法暫時不能得到很好地支持。這些不支持的寫法都可以通過其他寫法來規(guī)避,同時 ESLint 相關(guān)插件都能很好地提醒用戶避免踩坑。了解 Taro 這些注意事項后,接下來我們就來動手實現(xiàn)一個簡單的 Todo 項目。

感謝你能夠認真閱讀完這篇文章,希望小編分享taro和react有什么區(qū)別內(nèi)容對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,遇到問題就找億速云,詳細的解決方法等著你來學(xué)習(xí)!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI