使用 MobX

2020-05-12 17:47 更新
自 1.2.0-beta.1 開(kāi)始支持

MobX 為復(fù)雜項(xiàng)目中狀態(tài)管理提供了一種簡(jiǎn)單高效的機(jī)制;Taro 提供了 @tarojs/mobx 來(lái)讓開(kāi)發(fā)人員在使用 MobX 的過(guò)程中獲得更加良好的開(kāi)發(fā)體驗(yàn)。

安裝

$ yarn add mobx@4.8.0 @tarojs/mobx @tarojs/mobx-h5 @tarojs/mobx-rn
# 或者使用 npm
$ npm install --save mobx@4.8.0 @tarojs/mobx @tarojs/mobx-h5 @tarojs/mobx-rn

API

onError

Mobx 異常監(jiān)聽(tīng)。

import { onError } from '@tarojs/mobx'

onError(error => {
  console.log('mobx global error listener:', error)
})

isUsingStaticRendering

自 1.3.6 開(kāi)始支持

判斷是否開(kāi)啟了服務(wù)端渲染(該狀態(tài)為全局狀態(tài))。

import { isUsingStaticRendering } from '@tarojs/mobx'

if (isUsingStaticRendering()) {
  //...
}

useStaticRendering

自 1.3.6 開(kāi)始支持

服務(wù)端渲染狀態(tài)設(shè)置(該狀態(tài)為全局狀態(tài))。

import { useStaticRendering } from '@tarojs/mobx'

useStaticRendering(false)

useLocalStore

自 1.3.6 開(kāi)始支持

將對(duì)象轉(zhuǎn)換為 observable 對(duì)象,其中 getter 會(huì)被轉(zhuǎn)換為 computed 屬性,方法會(huì)與 store 進(jìn)行綁定并自動(dòng)執(zhí)行 mobx transactions,比如:

import Taro from '@tarojs/taro'
import { View, Text, Button } from '@tarojs/components'
import { useLocalStore,  observer } from '@tarojs/mobx'

import './index.scss'

function Index() {
  const store = useLocalStore(() => ({
    counter: 0,
    increment() {
      store.counter++
    },
    decrement() {
      store.counter--
    },
    incrementAsync() {
      setTimeout(() => store.counter++, 1000)
    }
  }))

  const { counter, increment, decrement, incrementAsync } = store;
  return (
    <View>
      <Button onClick={increment}>+</Button>
      <Button onClick={decrement}>-</Button>
      <Button onClick={incrementAsync}>Add Async</Button>
      <Text>{counter}</Text>
    </View>
  )
}

export default observer(Index)

useAsObservableSource

自 1.3.6 開(kāi)始支持

與 useLocalStore 的區(qū)別是,它將純(不包含 getter 或方法)對(duì)象轉(zhuǎn)換為 observable,主要使用場(chǎng)景為:

  • 如果對(duì)象某個(gè)屬性的值需經(jīng)過(guò)復(fù)雜運(yùn)算才能獲得,可通過(guò)該方法進(jìn)行包裝,這樣在組件的生命周期中該運(yùn)算只需要運(yùn)算一次。
  • 一般情況下 useLocalStore 僅用于組件內(nèi)部,如果 useLocalStore 中的對(duì)象需要依賴外部傳遞的屬性,那么可通過(guò) useAsObservableSource 將這些屬性進(jìn)行轉(zhuǎn)換,而后在 useLocalStore 對(duì)象中進(jìn)行引用,這樣在外部屬性改變時(shí)自動(dòng)通知 useLocalStore 對(duì)象對(duì)變化進(jìn)行響應(yīng),比如:import Taro from '@tarojs/taro' import { View, Button, Text } from '@tarojs/components' import { useAsObservableSource, useLocalStore, observer } from '@tarojs/mobx' function Multiplier(props) { const observableProps = useAsObservableSource(props) const store = useLocalStore(() => ({ counter: 1, get multiplied() { return observableProps.multiplier * store.counter }, increment() { store.counter += 1 } })) const { multiplier } = observableProps const { multiplied, counter, increment } = store return ( <View> <Text>multiplier({multiplier}) * counter({counter}) = {multiplied}</Text> <Button onClick={increment}>Increment Counter</Button> </View> ) } export default observer(Multiplier) 該場(chǎng)景也可直接使用 useLocalStore 中的第二種用法來(lái)實(shí)現(xiàn):import Taro from '@tarojs/taro' import { View, Button, Text } from '@tarojs/components' import { useLocalStore, observer } from '@tarojs/mobx' function Multiplier(props) { const store = useLocalStore(source => ({ counter: 1, get multiplier() { return source.multiplier }, get multiplied() { return source.multiplier * store.counter }, increment() { store.counter += 1 } }), props) const { multiplied, counter, increment, multiplier } = store return ( <View> <Text>multiplier({multiplier}) * counter({counter}) = {multiplied}</Text> <Button onClick={increment}>Increment Counter</Button> </View> ) } export default observer(Multiplier)

observer

將組件設(shè)置為監(jiān)聽(tīng)者,以便在可觀察對(duì)象的值改變后觸發(fā)頁(yè)面的重新渲染。

注:

  • 不要在 JSX 中對(duì)可觀察對(duì)象進(jìn)行引用,比如:// 錯(cuò)誤,在小程序中值改變后將無(wú)法觸發(fā)重新渲染 const { counterStore } = this.props return ( <Text>{counterStore.counter}</Text> ) // 正確 const { counterStore: { counter } } = this.props return ( <Text>{counter}</Text> ) 這是因?yàn)?nbsp;@tarojs/mobx 通過(guò)監(jiān)聽(tīng)組件的 render(小程序編譯后為 _createData)方法來(lái)觸發(fā)更新;在小程序中,JSX 的代碼會(huì)被編譯到 wxml 文件中,此時(shí)對(duì)可觀察對(duì)象的引用(比如:counterStore.counter)早已脫離了 @tarojs/mobx 的監(jiān)控,故此對(duì)該屬性的更改并不會(huì)觸發(fā)更新操作。
  • 如使用 @observable 裝飾器來(lái)定義可觀察對(duì)象時(shí),請(qǐng)確保該屬性已經(jīng)初始化,比如:@observable counter // 錯(cuò)誤,值改變后將無(wú)法觸發(fā)重新渲染 @observable counter = 0 // 正確
  • 如果 isUsingStaticRendering 為 true,該方法不做任何事情。

Provider

全局 store 設(shè)置,比如:

import Taro, { Component } from '@tarojs/taro'
import { Provider } from '@tarojs/mobx'
import Index from './pages/index'
import counterStore from './store/counter'

const store = {
  counterStore
}

class App extends Component {
  config = {
    pages: [
      'pages/index/index'
    ],
    window: {
      backgroundTextStyle: 'light',
      navigationBarBackgroundColor: '#fff',
      navigationBarTitleText: 'WeChat',
      navigationBarTextStyle: 'black'
    }
  }

  render () {
    return (
      <Provider store={store}>
        <Index />
      </Provider>
    )
  }
}

Taro.render(<App />, document.getElementById('app'))

注:

  • Provider 必須作用于入口文件(即:src/app.js),在其他地方使用無(wú)效。
  • 不支持嵌套,即全局只能存在一個(gè) Provider。
  • 在 mobx-react 中,可通過(guò)以下方式設(shè)置 store:<Provider store1={xxxx} store2={xxxx}> <XXX /> </Provider> 而在 @tarojs/mobx 中,我們需要使用以下方式設(shè)置:const store = { store1: xxxx, store2: xxxx } <Provider store={store}> <XXX /> </Provider>

inject

將 Provider 中設(shè)置的 store 提取到組件的 props 中,該 API 只適用于類組件,比如:

import Taro, { Component } from '@tarojs/taro'
import { observer, inject } from '@tarojs/mobx'

import './index.scss'

@inject('counterStore')
@observer
class Index extends Component {
  //...
}

export default Index

import Taro, { Component } from '@tarojs/taro'
import { observer, inject } from '@tarojs/mobx'

import './index.scss'

@inject((stores, props) => ({
  counterStore: stores.counterStore
}))
@observer
class Index extends Component {
  //...
}

export default Index

注:

  • 無(wú)論以何種方式使用 inject,其后的 observer 均不能省略。
  • 不要在 inject 中引用可觀察對(duì)象,這將導(dǎo)致屬性改變后頁(yè)面不更新,比如:// 錯(cuò)誤 @inject((stores, props) => ({ counter: stores.counterStore.counter })) // 正確 @inject((stores, props) => ({ counterStore: stores.counterStore }))

PropTypes

自 1.3.6 開(kāi)始支持

@tarojs/mobx 提供了以下 PropTypes 來(lái)驗(yàn)證 Mobx 的結(jié)構(gòu):

  • observableArray
  • observableArrayOf
  • observableMap
  • observableObject
  • arrayOrObservableArray
  • arrayOrObservableArrayOf
  • objectOrObservableObject


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)