性能優(yōu)化實踐

2020-05-12 17:47 更新

開發(fā)者手動優(yōu)化

開發(fā)者可以借助 Taro 提供的各種工具對程序性能進行優(yōu)化。

預加載

在微信小程序、支付寶小程序和QQ輕應用中,從調(diào)用 Taro.navigateTo 或 Taro.redirectTo 后,到頁面觸發(fā) componentWillMount 會有一定延時。因此一些網(wǎng)絡請求可以提前到發(fā)起跳轉(zhuǎn)前一刻去請求。

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

注意:調(diào)用跳轉(zhuǎn)方法時需要使用絕對路徑,相對路徑不會觸發(fā)此鉤子。

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

在小程序中,可以使用 this.$preload 函數(shù)進行頁面跳轉(zhuǎn)傳參

用法:this.$preload(key: String | Object, [ value: Any ])

之所以命名為 $preload,因為它也有一點預加載數(shù)據(jù)的意味。

如果覺得每次頁面跳轉(zhuǎn)傳參時,需要先把參數(shù) stringify 后加到 url 的查詢字符串中很繁瑣,可以利用 this.$preload 進行傳參。

另外如果傳入的是下一個頁面的數(shù)據(jù)請求 promise,也有上一點提到的“預加載”功能,也能夠繞過 componentWillMount 延時。不同點主要在于代碼管理,開發(fā)者可酌情使用。

例子:

// 傳入單個參數(shù)

// A 頁面
// 調(diào)用跳轉(zhuǎn)方法前使用 this.$preload
this.$preload('key', 'val')
Taro.navigateTo({ url: '/pages/B/B' })

// B 頁面
// 可以于 this.$router.preload 中訪問到 this.$preload 傳入的參數(shù)
componentWillMount () {
  console.log('preload: ', this.$router.preload.key)
}
// 傳入多個參數(shù)

// A 頁面
this.$preload({
  x: 1,
  y: 2
})
Taro.navigateTo({ url: '/pages/B/B' })

// B 頁面
componentWillMount () {
  console.log('preload: ', this.$router.preload)
}

shouldComponentUpdate

當你清楚在某些情況下組件不需要被重新渲染時,可以通過在 shouldComponentUpdate 鉤子里返回 false 來跳過本次渲染流程。

shouldComponentUpdate (nextProps, nextState) {
  if (this.props.color !== nextProps.color) {
    return true
  }
  if (this.state.count !== nextState.count) {
    return true
  }
  return false
}

Taro.PureComponent

在大多數(shù)情況下,開發(fā)者可以讓組件繼承于 Taro.PureComponent 類,而無需手動實現(xiàn) shouldComponentUpdate。Taro.PureComponent 里實現(xiàn)了 shouldComponentUpdate,它會把新舊 props 和新舊 state 分別做一次淺對比,以避免不必要的渲染。

Taro.memo

自 v1.3.0 可用

Taro.memo 是一個高階組件,它和 PureComponent 非常相似。但它適用于函數(shù)式組件,而非 Class 組件。

如果你的函數(shù)組件在給定相同 props 的情況下渲染相同的結(jié)果,那么你可以通過將其包裝在 Taro.memo 中調(diào)用,以此通過記憶組件渲染結(jié)果的方式來提高組件的性能表現(xiàn)。這意味著在這種情況下,Taro 將跳過渲染組件的操作并直接復用最近一次渲染的結(jié)果。

默認情況下其只會對復雜對象做淺層對比(和 PureComponent 行為一致),如果你想要控制對比過程,那么請將自定義的比較函數(shù)通過第二個參數(shù)傳入來實現(xiàn)。

function MyComponent(props) {
  /* 使用 props 渲染 */
}
function areEqual(prevProps, nextProps) {
  /*
  如果把 nextProps 傳入 render 方法的返回結(jié)果與
  將 prevProps 傳入 render 方法的返回結(jié)果一致則返回 true,
  否則返回 false
  */
}
export default Taro.memo(MyComponent, areEqual);
注意 與 class 組件中 shouldComponentUpdate() 方法不同的是,如果 props 相等,areEqual 會返回 true;如果 props 不相等,則返回 false。這與 shouldComponentUpdate 方法的返回值相反。

Taro 框架層面優(yōu)化

Taro 框架做了一些性能優(yōu)化方面的工作,這部分毋需開發(fā)者手動處理,開發(fā)者可稍做了解。

小程序數(shù)據(jù) diff

在真正調(diào)用小程序的 setData 方法之前,Taro 會把頁面或組件的 state 和當前頁面或組件的 data 做一次 diff,只對必要更新的數(shù)據(jù)做 setData,開發(fā)者無需手動優(yōu)化。

diff 邏輯:
  1. 全等 => 跳過
  2. 新增字段 => 使用新值
  3. 類型不同 => 使用新值
  4. 類型相同、基礎(chǔ)數(shù)據(jù)類型 => 使用新值
  5. 其中一方為數(shù)組,另一方不是 => 使用新值
  6. 都為數(shù)組、新數(shù)組比舊數(shù)組短 => 使用新值
  7. 都為數(shù)組、新數(shù)組長度大于等于舊數(shù)組的長度 => 逐項 diff、按路徑更新
  8. 其中一方為 null,另一方不是 => 使用新值
  9. 都為對象,新對象缺少舊對象某些屬性 => 使用新值
  10. 都為對象,新對象擁有舊對象所有的屬性 => 逐項 diff、按路徑更新

例子:

// 新值
const state = {
  a: 1,
  b: 22,
  d: 4,
  list: [1],
  arr: [1, 'a', true, null, 66],
  obj: {
    x: 5
  },
  foo: {
    x: 8,
    y: 10,
    z: 0
  }
}

// 舊值
const data = {
  a: 1,
  b: 2,
  c: 3,
  list: [1, 2, 3],
  arr: [1, 2, 3],
  obj: {
    x: 10,
    y: 8
  },
  foo: {
    x: 'xxx',
    y: 10
  }
}

diff(data, state)
/**
 * diff 結(jié)果
{
  b: 22,
  d: 4,
  list: [ 1 ],
  'arr[1]': 'a',
  'arr[2]': true,
  'arr[3]': null,
  'arr[4]': 66,
  obj: { x: 5 },
  'foo.x': 8,
  'foo.z': 0
}
*/


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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號