记录在开发过程中踩的坑(1)
使用的技术栈是react + react-router + ts + webpack,刚开始使用react各种不顺手,但是习惯了还是挺香的,这次写的是一些简单的需求,所以用的函数组件和一些hooks完成的,这篇文章主要写的是我遇到的坑以及怎么解决的,防止再次踩坑...
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:封装组件, 类似于如下图, 此组件是用来做单选的
因为在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不熟悉,所以对于我来说还是有点挑战的,还好有某个人的指导,顺利解决了这个问题,哈哈)
我的解决办法: 利用父子组件之间的相互传值(以下是大致代码片段)
这是在父组件里面使用的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
来取值,但是却实现不了最后一个需求--输入框内预设的格式文案可以删除,又要有预设文案, 又要可以删除,且预设文案是换行显示的,我找了很多方法,最后终于实现了...
解决办法: 用的是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';
}
};
总结: 差不多就是这些坑了, 后面也会一点一点的做记录, 希望踩过的坑就这样过去了,下次再遇到一眼就能认出来,及时解决,哈哈哈!!第一次写,可能有很多不足之处,如果有看到的大佬希望可以指点指点,倍感荣幸!