第一个react项目, 踩坑记录(1)

486 阅读4分钟

记录在开发过程中踩的坑(1)

使用的技术栈是react + react-router + ts + webpack,刚开始使用react各种不顺手,但是习惯了还是挺香的,这次写的是一些简单的需求,所以用的函数组件和一些hooks完成的,这篇文章主要写的是我遇到的坑以及怎么解决的,防止再次踩坑...

image.png

1. 处理填写金额的input框 (输入的值是大于等于0的数字且这个值可为空)

注意: 千万不要使用 <input type="number" />去做限制, 会踩坑!!!!

坑位1: input的type属性为number的时候,还是可以输入符号 - + . 输入--1 或 -1- 或 09-1.9- 时,很显然是不符合的,input会给这些值转成空的字符串 '',所以做判断的时候不能这样写if(value>=0 && value){...} 虽然这样写满足value大于等于0的条件,但是忽略了vuelue可为空的条件.....

我的解决办法:

<input type="text" maxLength={20} onChange={getValue} onBlur={requireReg} 使用正则表达式去限制

const [value, setValue] = useState('');
const requireReg = () => {
    const reg = /(^(([0-9]([0-9]+)?)|(0{1}))(\.[0-9]{1,2})?$)/;
    if (value && !reg.test(value)) { //不符合条件,弹框提示
      showToast({
        type: 'text',
        text: '请写大于等于0的数字'
      });
      return;
    }
}
const getValue = (event) => { //这一段是限制用户输入的金额只能有2位小数点(类似于微信输入金额的格式)
    const reg = /^(-)*(\d+)\.(\d\d).*$/;
    let value = event.target.value.replace(reg, '$1$2.$3') || '';
    setValue(value);
}

坑位2:封装组件, 类似于如下图, 此组件是用来做单选的

image.png

因为在popup组件的父组件加了一个position: relative, 所以如果用定位position: absolute,会根据其父元素的位置定位,为了脱离这个位置,我使用了position: fixed;bottom: 0px;left:50%;transform:translateX(-50%);将其固定在屏幕底部以及中间位置,黑色遮罩层设置position: absolute, 脱离文档流

注意: 一定要将popup组件内的内容居中,不然横屏展示的时候, 或者在PC端看到的时候, 黑色遮罩层在屏幕最左边,你会看的一脸懵!!!! 我是这样写的------上主要代码-----

//这是popup组件整体样式
.popup {
  position: fixed;
  width: 100%;
  max-width: 480px;
  height: 100vh;
  left: 50%;
  transform: translateX(-50%);
  bottom: 0px;
  z-index: 999;
  overflow-y: hidden;
  touch-action: none;
}
//这是遮罩层样式
.mask {
  width: 100%;
  height: 100%;
  position: absolute;
  background-color: rgba(0, 0, 0, 0.8);
}
//这是单选form的样式
.popupForm {
  width: 100%;
  max-height: 360px;
  min-height: 250px;
  background-color: #ffffff;
  border-radius: 10px 10px 0px 0px;
  overflow: auto;
  position: absolute;
  bottom: 0px;
}

在封装组件的时候,一定要问清楚后端,传过去的值是option还是value,不然后面改组件会很麻烦.....我就是先封装好组件后再问的,后悔!!!!

(因为我之前用的是Vue,对react不熟悉,所以对于我来说还是有点挑战的,还好有某个人的指导,顺利解决了这个问题,哈哈)

image.png

我的解决办法: 利用父子组件之间的相互传值(以下是大致代码片段)

这是在父组件里面使用的popup组件
<Popup
    popupInfo={popupInfo}
    value={values[popupInfo.key]}
    onClose={() => setVisible(false)}
    onPick={(value) => {
      setCurrVal(value);
    }}
/>
这是popup组件
export default memo(function Popup(props: Props) {
  const { onClose, onPick, value, popupInfo } = props;
  const [pick, setPick] = useState<number>(0);

  const pickItem = (value: string, key: number) => {//点击每一项时,赋值
    onPick(value);
    setPick(key);
    onClose(); //关闭弹窗
  };

  useEffect(() => {
    setPick(popupInfo.select.indexOf(value));
    onPick(value); //为了在选择的时候为空,也赋值为空
  }, [popupInfo, value]);
}

坑位三: 需求是在一个框内能够输入,输入框随字数增加可扩充高度,输入框内预设的格式文案可以删除 我之前用的方法是<div contentEditable ref={divRef} />,因为通过CSS就可以实现输入框随字数增加可扩充高度这个需求,可通过 const divRef = useRef<any>(); divRef.current.textContent来取值,但是却实现不了最后一个需求--输入框内预设的格式文案可以删除,又要有预设文案, 又要可以删除,且预设文案是换行显示的,我找了很多方法,最后终于实现了...

image.png

解决办法: 用的是textarea, 通过js动态改变textarea的高度,预设文案可以使用defaultValue属性,文案是换行显示的,所以使用\n来转换,为什么我用的是defaultValue而不是value呢? 因为使用value的话, 将预设文案删除后,value

const defaultValue = `我的名字:\n\n我的性别:\n\n我的年龄:`;
<textarea
    ref={refArea}
    className={style['textarea']}
    defaultValue={value ? value : defaultValue}
    onChange={(event) => {
      setValue(event.target.value);
      resize();
    }}
/>
//重置textarea高度
  const resize = () => {
    if (refArea.current) {
      refArea.current.style.height = 'auto';
      refArea.current.style.height = refArea.current.scrollHeight + 'px';
    }
  };

总结: 差不多就是这些坑了, 后面也会一点一点的做记录, 希望踩过的坑就这样过去了,下次再遇到一眼就能认出来,及时解决,哈哈哈!!第一次写,可能有很多不足之处,如果有看到的大佬希望可以指点指点,倍感荣幸!