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,从而出错。

  • 原因:

查看编译后的代码发现,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 
  });
}

复制代码

解决方案:

不要使用解构,以下是部分代码

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下的该变量,使得渲染错误。

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将代码编译的风马牛不相及,导致出现了不可预料的错误

// 编译给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太辣鸡

解决:

把里面的三元表达式赋值给一个变量

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确有其值。

原因

待确定

解决方案:

只需要在最外层包裹一个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的最佳实践

最后如果觉得本文有帮助 记得点赞三连哦 十分感谢

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享