Taro中曾遇到的那些天坑

前言

當前項目組用的 版本是Taro v2.2.16小程序

多層嵌套循環的數據解構時取值有問題

栗子:

import Taro from '@tarojs/taro';
import { View } from '@tarojs/components';
class A extends Taro.Component {
  data = [
    {
      title: '項目1',
      type: 1,
      children: [{ title: '項目1-1' }, { title: '項目1-2' }],
    },
    {
      title: '項目2',
      type: 2,
      children: [{ title: '項目2-1' }, { title: '項目2-2' }],
    },
  ];
  render() {
    return (
      <View>
        {this.data.map((outItem) => {
          const { title, type, children } = outItem;
          return (
            <View>
              <View>{title}</View>
              <View>
                {children.map((innerItem) => {
                  console.log(type); // 問題點所在,會打印出undefined
                  return (
                    <View>
                      {type === 1 && <View>{innerItem.title} - 類型一</View>}
                      {type === 2 && (
                        <View>{innerItem.title} - 這是一個類型二</View>
                      )}
                    </View>
                  );
                })}
              </View>
            </View>
          );
        })}
      </View>
    );
  }
}
export default A;

複製代碼

現象:

上面的console.log理應正常打印出type的值,可是Taro編譯後,會打印出undefined。顯而易見,下面的條件判斷所有都會是false,從而出錯。markdown

  • 緣由:

查看編譯後的代碼發現,Taro會對map中的代碼進行編譯,編譯結果大體以下函數

var loopArray128 = data.map(function (outItem) {
  var outItem = {
    $original: (0, _index.internal_get_original)(outItem)
  }
  var _outItem$$original = outItem.$original,
      title = _outItem$$original.title,
      type = _outItem$$original.type,
      children = _outItem$$original.children;
  var $anonymousCallee__36 = children.map(function (innerItem) {
    innerItem = {
      $original: (0, _index.internal_get_original)(innerItem)
    };
    console.log(outItem.type); // 最後會編譯成這樣 outItem.type就不能取到想要的值了
    // ... other code 
  });
}

複製代碼

解決方案:

不要使用解構,如下是部分代碼oop

render() {
    return (
      <View>
        {this.data.map((outItem) => {
          const { title, children } = outItem;
          return (
            <View>
              <View>{title}</View>
              <View>
                {children.map((innerItem) => {
                  console.log(outItem.type); // 此時會編譯成outItem.$original.type 值正常打印
                  return (
                    <View>
                      {type === 1 && <View>{innerItem.title} - 類型一</View>}
                      {type === 2 && (
                        <View>{innerItem.title} - 這是一個類型二</View>
                      )}
                    </View>
                  );
                })}
              </View>
            </View>
          );
        })}
      </View>
    );
  }

複製代碼

props和state使用一樣的變量名

栗子:

class Demo {
  state = {
    operationKeys: []
  }
  
  render() {
    const { operationKeys } = this.props
    console.log('operationKeys', operationKeys, operationKeys.length > 0)
    return (
      <View>
        {operationKeys.length > 0 ? (
          <View>has data</View>
        ) : (
          <NoData/>
        )}
      </View>
    )
  }
}

複製代碼

現象:

組件在 props.operationKeys.length > 0 爲true時,始終渲染佈局

緣由:

Taro在編譯 tsx(或jsx) 時,會將 js 邏輯和模板分離,js部分邏輯會根據 jsx 中的分支判斷,生成一個 data,用於給模板進行渲染。jsx 中的標籤部分會編譯成wxml。若是props和state用了一樣的變量名,而且state不更新,會致使渲染的時候一直使用state下的該變量,使得渲染錯誤。flex

JSX中三元表達式的嵌套也可能有問題(神奇的Taro)

栗子:

{isSomething ? (
  <View className="row">
    <View className="row-title">栗子</View>
    <View className="row-content">
      {Boolean(tampArrayList)
        ? tampArrayList.map((item, i) => (
        <View key={item.id + `${i}`}>
          {`${item.name}*${item.num},${item.content}`}
        </View>
      ))
      : '-'}
    </View>
  </View>
) : null}

複製代碼

現象:

taro將代碼編譯的風馬牛不相及,致使出現了不可預料的錯誤this

// 編譯給wxml用的變量
var anonymousState__temp5 = Boolean(tampArrayList);
// 這裏不知道爲何省去了Boolean(tampArrayList)的表達式
// 致使tampArrayList.map報了Error
var loopArray197 = isWeddingPhoto ? tampArrayList.map(function (item, i) {
  item = {
    $original: (0, _index.internal_get_original)(item)
  };
  // 這裏又神奇的出現了Boolean(tampArrayList)的表達式
  // $loopState__temp3爲wxml使用的key值,根本與anyArrayList的狀態無關
  var $loopState__temp3 = Boolean(anyArrayList) ? item.$original.id + ("" + i) : null;
  return {
    $loopState__temp3: $loopState__temp3,
    $original: item.$original
  };
}) : [];
複製代碼

緣由:

Taro太辣雞spa

解決:

把裏面的三元表達式賦值給一個變量code

render() {
  const productList = Boolean(tampArrayList)
    ? tampArrayList.map((item, i) => (
      <View key={item.id + `${i}`}>
        {`${item.name}*${item.num},${item.content}`}
      </View>
    ))
    : '-';
  // ...
  return (
    <View className="row-content">{productList}</View>
  )
}

複製代碼

還有一些 還沒找到緣由 但憑藉踩坑經驗 卻順利解決了的

scroll-view使用flex佈局,可能出現無效的狀況(神奇的小程序)

自定義組件內傳入組件做爲節點渲染出錯

栗子:

import Taro from '@tarojs/taro';
import { View, Input } from '@tarojs/components';
// Cell是一個自定義組件,title是標題,renderContent傳入DOM用於渲染內容
import { Cell } from '@components/index';
class A extends Taro.Component {
  data = [
    {
      title: '標題一',
      content: '輸入的內容111',
    },
    {
      title: '標題二',
      content: '輸入的內容222',
    },
  ];
  render() {
    return (
      <View>
        {this.data.map((item) => {
          const { title, content } = item;
          return (
            <Cell
              title={title}
              renderContent={<Input placeholder="請輸入" value={content} />}
            />
          );
        })}
      </View>
    );
  }
}

複製代碼

現象:

Input的value值沒有按照預想的顯示出來。但content確有其值。component

緣由

待肯定

解決方案:

只須要在最外層包裹一個View便可解決這個問題。

<Cell
  title={title}
  renderContent={
    <View>
      <Input placeholder="請輸入" value={content} />
    </View>
  }
 />

複製代碼

解構store中的方法後傳入自定義組件編譯報錯

import Taro from '@tarojs/taro';
import { View, Input } from '@tarojs/components';
// Cell是一個自定義組件,onClick是一個自定義的點擊事件
import { Cell } from '@components/index';
// Store是用於存儲數據的類(mobx)
import Store from './store';
class A extends Taro.Component {
  store = new Store();
  
  render() {
    const { name, handleClick } = this.store;
    return (
      <View>
        <View onClick={handleClick}>{name}</View>
        <Cell onClick={handleClick} />
      </View>
    );
  }
}
export default A;

複製代碼

現象

自定義組件Cell傳入自定義方法以後,編譯會出問題。可是View彷佛就沒有問題。

緣由

待肯定

解決

直接傳入方法,或者使用匿名函數包裹。如下是部分代碼:

<Cell onClick={() => handleClick()} />
// or
<Cell onClick={this.store.handleClick} />

複製代碼

總結

  • 以上問題 有些Taro3中已經解決 但Taro 依舊有些坑,當個人迭代任務工做中百思不得其解的時候 就會在出問題的那個jsx 元素外層再包一層<View> 這是一個偷懶行爲。但真的很管用

  • 其次:遇到問題的時候能夠先再去過一遍Taro的最佳實踐

最後若是以爲本文有幫助 記得點贊三連哦 十分感謝

相關文章
相關標籤/搜索