react jsx 中使用 switch case 示例
在JSX的render html中无法写类似if,switch这样的语法,但是可以写函数或者三元表达式。所以可以利用一个立即执行的匿名函数来包装你的方法。
<div> <span>适用平台:</span> <span>{(() => { switch (currentItems.usePlatform) { case 0: return '全平台可用' case 1: return '淘宝' case 2: return '美团' case 3: return '爱奇艺' case 4: return '腾讯' default: return null } } )()}</span> </div>去除数组中的空数组
// 去除数组中的空数组 var arr = [undefined,undefined,1,'','false',false,true,null,'null']; arr.filter(item=>item) console.log(arr.filter(item=>item)) // [1, "false", true, "null"]跳出forEach循环的方法,因为forEach中不能使用continue与break,所以可以用try,catch去抛出一个异常,然后捕获的方式去终断它。
var arr = [1,2,3,5]; try { arr.forEach(item => { if (item === 2) { throw new Error('错误') } console.log(item); // 1 }); } catch (e) { console.log(e.message); // 错误 } console.log('之后的执行函数') // 之后的执行函数也可以使用some,every,find来跳出循环,every return false可以跳出循环, some,find return true可以跳出循环。
var arr = [1,2,3,5]; arr.some(item => { console.log('item', item) // 1 2 return item === 2 }) console.log('之后的执行函数') var arr = [1,2,3,5]; arr.find(item => { console.log('item', item) // 1 2 return item === 2 }) console.log('之后的执行函数')
一个list数组,算出order相同下相应scale相加的总和。使用reduce可以更加简单方便。
var list = [{order:1, scale:10}, {order:2, scale:200}, {order:1, scale:10}, {order:1, scale:80}, {order:3, scale:120}]; var c = list.reduce((pre, cur) => (pre[cur.order] = (pre[cur.order] || 0) + cur.scale) && pre, {}) // 等价于 var c = list.reduce((pre, cur) => { pre[cur.order] = (pre[cur.order] || 0) + cur.scale; return pre; }, {}); console.log(c) // {1: 100, 2: 200, 3: 120}
已知年月,求该月共多少天?
在写日历组件时,曾遇到 已知年月,求该月共多少天? 这样的需求。
最开始思路会是:
先判断该年份是否是闰年,来处理 2 月份情况,闰年 2 月共 29 天,非闰年 2 月共 28 天再判断其他月份,如 1 月共 31 天,4 月共 30 天代码就不一一列出了,思路代码啥的没啥问题。
这里其实有种更简便的方法,借助 Date API 处理日期溢出时,会自动往后推延响应时间的规则,直接上代码:
// month 值需对应实际月份减一,如实际 2 月,month 为 1,实际 3 月,month 为 2 function getMonthCountDay (year, month) { return 32 - new Date(year, month, 32).getDate() }验证下:
// 求闰年的 2 月份总天数 getMonthCountDay(2000, 1) // 29 // 求 1 月份总天数 getMonthCountDay(2000, 0) // 31 getMonthCountDay(2001, 0) // 31 // 求 4 月份总天数 getMonthCountDay(2000, 3) // 30 getMonthCountDay(2001, 3) // 30类似于加法进位,减法退位。
new Date(2019, 0, 50)其中0代表1月,1月只有31天,则多出来的19天会被加到2月,结果是2019年2月19日。new Date(2019, 20, 10),1年只有12个月,多出来的9个月会被加到2020年,结果是2020年9月10日new Date(2019, -2, 10),2019年1月10日往前推2个月,结果为2018年11月10日new Date(2019, 2, -2),2019年3月1日往前推2天,结果为2019年2月26日以上可以混用
https://github.com/ant-design/ant-design/issues/13825
antd 表格设置width不起作用
在本地时间转化为时间戳的时候,要使用/,如用new Date('2019-11-4 23:59:59')的时候,在PC端没有问题,但是手机端会出现报错。
const endTime = new Date('2019/11/4 23:59:59');
之前升级下了package.json里面的包,结果一直提示如下报错
.git/hooks/pre-commit: line 2: ./node_modules/_pre-commit@1.2.2@pre-commit/hook: No such file or directory
其实解决办法很简单,rm -rf .git/hooks/pre-commit,删除掉这个东西然后重新install一下node_modules就可以了。
第一种办法是常见的 将真实的radio,checkbox等元素透明度设为0,定位在美化的图片上面,然后去操作。
第二种的话可以利用css去操作,核心
一是伪类选择器 :checked,表示对应控件元素(单选框或是复选框)选中时的样式;二就是加号 + 相邻兄弟选择器,这个符号表示选择后面的兄弟节点。于是,两者配合,就可以轻松自如控制后面元素的显示或者隐藏,或是其他样式了。
而如何让单复选框选中和不选中了,那就是 label 标签了哈,for 属性锚定对应的单选框或是复选框,然后点击这里的 label 标签元素的时候,对应的单复选框就会选中或是取消选中。然后,就有上面的效果啦!
<style> .checkbox-name { vertical-align: middle; font-size: 16px; } .checkbox-beauty { width: 15px; height: 15px; line-height: 15px; text-align: center; border: 1px solid #ccc; display: inline-block; margin: 0 15px 0 3px; vertical-align: middle; } input[type="checkbox"]:checked+.checkbox-beauty::after { content: '✓'; font-size: 16px; font-weight: bold; color: green; } .checkbox-beauty:hover { box-shadow: 0 0 7px green; } </style> <div> <span class="checkbox-name">香蕉</span> <input type="checkbox" name="checkboxName" id="checkboxName2" hidden/> <label for="checkboxName2" class="checkbox-beauty"></label> </div>
在发送验证码的场景中,一般最外层的盒子设置为弹性盒子,左边和右边的写成固定宽度,中间的input输入框设置为flex:1,希望input的宽度是所剩下的长度,结果是它比所剩下的长度要大,验证码这三个字就显示成两行了
原因是:input兼容弹性盒子有问题,它会有一个自己默认的最小长度,所以会导致验证码显示成两行
解决办法:我们可以给input输入框加一个div父元素,然后这个div设置flex:1,input设置width:100%;即可解决问题
这是因为React里面的事件并不是真实的DOM事件,而是自己在原生DOM事件上封装的合成事件。 合成事件是由事件池来管理的,合成事件对象可能会被重用,合成事件的所有属性也会随之被清空。所以当在异步处理程序(如setTimeout等等)中或者浏览器控制台中去访问合成事件的属性,有可能就是空的。 上面的答案中给出的方案:event.persist(),其实就是将当前的合成事件从事件池中移除了,所以能够继续保有对该事件的引用以及仍然能访问该事件的属性。
解决办法: 使用深拷贝,或者页面不要使用 PureComponent
声明两个数组, 一个数组 arr: [0], // 数组key 来存放循环key值,一个 renderDetailList:[] // 数据list,用来渲染数据。注意的是存放key的这个数组是必须的,且新增要用如下方法,保持它是自增的。之前使用index作为循环的key值,就会出现删除某列以后,key值绑定混乱的情况。
PS: 之前试过将每一列单独抽一个子组件来实现,都是一个独立的form表单,最后提交的时候再去拼接数组。也可以实现功能,但是会很繁琐,不建议使用。
if (arr && arr.length > 0) { arr.push(arr[arr.length - 1] + 1); } else { arr.push(0); }{ arr && arr.map((val, i) => { return ( <div className="product-detail-container" key={val}> <Form layout="inline"> <Form.Item key="lib" label="险种大类" > {getFieldDecorator(`data[${val}].lib`, { initialValue: renderList[i] && renderList[i].lib ? renderList[i].lib : null, rules: [ { required: true, message: '不能为空' }, ], })( <Select> <Select.Option key="1" value="1">重疾</Select.Option> <Select.Option key="2" value="2">定寿</Select.Option> <Select.Option key="2" value="3">意外</Select.Option> </Select>, )} </Form.Item> }
antd Select利用labelInValue属性使选择返回对象
function handleChange(value) { console.log(value); // { key: "lucy", label: "Lucy (101)" } } ReactDOM.render( <Select labelInValue defaultValue={{ key: 'lucy' }} style={{ width: 120 }} onChange={handleChange} > <Option value="jack">Jack (100)</Option> <Option value="lucy">Lucy (101)</Option> </Select>, mountNode, );默认情况下 onChange 里只能拿到 value,如果需要拿到选中的节点文本 label,可以使用 labelInValue 属性。
选中项的 label 会被包装到 value 中传递给 onChange 等函数,此时 value 是一个对象。
css中第一行首字变大,顶部无法对齐,或者有时因为设置了font-size,子元素无法在容器与顶部齐平。设置喜爱vertical-align: top就好了。
p:first-letter { font-size:20px; vertical-align:top; }
react中,有时候需要在你disabled中写一个函数来返回布尔值,但是却一直报错。(原因是我的函数里面有异步操作,比如setTiomout,导致在渲染的时候disabled还没有返回值,所以报错 ) 解决的话 这个函数必须是个同步函数。
<DatePicker style={{ width: 120 }} disabled={this.disabledMarkDate(i, list[i].disabled, disabled)} disabledDate={(e) => this.disabledDate(e, i)} />,
接受setTimeout中的返回值, 用回调的方法或者包一层promise
promise
// 校验是否是无效规则 isInvalid = (index) => { const { form: { getFieldsValue } } = this.props; // 因为表单的list是异步更新的,所以需要在setTimeout里面去才能访问到更新后的值 return new Promise(((resolve) => { setTimeout(() => { const itemVal = getFieldsValue().data[index]; const flag = itemVal.checkStatus === 0; // 将是否禁用开关返回 resolve(flag); }, 0); })); }; // 预停用时间禁用 (新增规则和修改无效规则时,此字段不可录入) disabledMarkDate = async (index, listDisabled, disabled) => { const flag = await this.isInvalid(index); return flag; };回调
checkOver(item,callback){ setTimeout(() => { let check = XXXX; callback&&callback(check) }, 1) } //调用 checkOver(item,function(check){ console.log(check) })
有时候在表单某个元素onChange的时候去获取表单的值,发现并不能获取到最新的值。最简单的办法是可以用setTimeout里面去异步就可以获取到。或者也可以使用表单的onValuesChange去实时获取每次表单更新时候得值。
Ant Design的表单onChange阶段不更新踩坑,以及修改表单值方法。
参考 https://blog.csdn.net/deng1456694385/article/details/86090884
antd 日期组件 (选择范围 大于等于开始时间,小于等于结束时间)。大于等于开始时间很简单,结果小于等于结束时间试了半天才知道endOf('day')就可以了
多看文档 https://momentjs.com/docs/#/parsing/is-valid/
disabledDate = (current) => { return current < moment(startTime) || current > moment(endTime).endOf('day'); };
antd表单中的validateFields没有被执行原因(多半是自定义校验写的有问题,callback有情况没有执行)
之前代码是这样写的,发现validateFields有事一直没触发,仔细检查是自己的 itemVal可能为undefined,导致callback永远不会被执行引起的
isExpiryRequred = (rule, value, callback, index) => { const { form: { getFieldsValue } } = this.props; const itemVal = getFieldsValue().data[index]; // 类型为活动,且状态无效时,必录终止时间 if (!value && itemVal.type === '1' && itemVal.commissionStatus === 0) { return callback('不能为空'); } return callback(); };在最开始时候 加个itemVal判断就行了
if (!itemVal) {
return callback();
}
https://blog.csdn.net/daihaoxin/article/details/106130597
antd table 行点击事件以及高亮显示选中行的背景颜色
rowClassName: 表格行的类名, 比如通过this.setRowClassName方法添加类名
onRow: 用于给表格添加事件, 如onClick, onMouseEnter 等内部事件
// 选中行 onClickRow = (record) => { return { onClick: () => { this.setState({ rowId: record.id, }); }, }; } setRowClassName = (record) => { return record.id === this.state.rowId ? 'clickRowStyl' : ''; } <Table pagination={dataPagination} columns={this.dataTableColumns} dataSource={this.dataSource} locale={{ emptyText: <NoContent/> }} onRow={this.onClickRow} rowClassName={this.setRowClassName} /> // 被选中的表格行的样式 .active { background-color #00b4ed; }
sticky 踩坑问题
1、父元素不能overflow:hidden或者overflow:auto属性。
2、必须指定top、bottom、left、right4个值之一,否则只会处于相对定位
3、父元素的高度不能低于sticky元素的高度
4、sticky元素仅在其父元素内生效
5、父元素设置display: flex,会导致子元素sticky失效,所以可用float布局代替
<style> .box { height: 1000px; } h1 { position: sticky; top: 100px; } </style> <body> <div class="box"> <h1>sticky</h1> </div> </body>如上,父元素box足够高,能撑开滚动条,就可以实现固定定位了,
但是如果里面再包一层div那就不行了(sticky元素仅在其父元素内生效)
<style> .box { height: 1000px; } h1 { position: sticky; top: 100px; } </style> <body> <div class="box"> <div> <h1>sticky</h1> </div> </div> </body>
Moment取最后一天,第一天方法
// 当月第一天开始时间 console.log(month.startOf('month').startOf('day').format('YYYY-MM-DD HH:mm:ss')); // 当月最后一天结束时间 console.log(month.endOf('month').endOf('day').format('YYYY-MM-DD HH:mm:ss'));
onblur和onclick事件冲突。(form中有一个input有失焦的校验,如果是在input聚焦的时候,直接点击保存提交表单,会发现提交的click没有触发,而是触发了input的失焦事件,原因是由于js的单线程机制和事件响应优先级的问题,onBlur总是比onClick先触发,即便同时绑定。)
https://www.zhihu.com/question/29623049
楼主说的情况不是事件冲突,⽽是⻚⾯结构变化导致绑定click的按钮没有被click到(这个你可以在click的 handler中打断点来验证)。 详细点说就是:点击时候input触发了blur,显示了错误消息(或其他⻚⾯结构变化),⽽这时候再松开⿏ 标,完成Click,但此时⿏标已经不在被绑定Click的元素上了,所以也就⽆法触发Click事件。 理解了Click事件的两步,这个问题就容易解决了,解决⽅案是⽤mousedown来代替click来绑定事件
解决方法1:
在失焦的事件里面设置个setTimeout延迟,保证在click之后才会触发,这样再点击提交click的时候,就会优于onBlur先触发onClick事件。
var tid; onBlur = function(){ tid = setTimeout(function(){ //do blur save }, 50); }; onClick = function(){ clearTimeout(tid); //do click save }解决方法2:
将onClick换成onMouseDown
PC浏览器预览打开doc,excel等格式方法。(移动端默认就可以打开) ,以下都是针对PC端的说明:
https://view.officeapps.live.com/op/view.aspx?src=${你文档的地址}` // 利用微软的在线文档打开(如果是pdf等浏览器识别的文件,正常点链接的话浏览器会尝试打开文件,直接下载文件,)
下面download的a标签,在同域情况下(资源(也就是图片) 和当前域名是同域的情况下),就会优先下载,如果跨域就会在浏览器中打开,但如果是浏览器不支持的格式依旧会下载(如zip,doc,excel等浏览器打不开的格式)。
比如在同域下,download PDF、图片, 就会是下载文件,而跨域就会直接在浏览器中打开。
<a href="money.PNG" download="a">xiazia</a>总结一句话, 资源文件同域下载,跨域优先打开,打不开就下载。