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
Date
API 处理日期溢出时,会自动往后推延响应时间的规则,那么具体的规则内容是什么?
类似于加法进位,减法退位。
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日- 以上可以混用
antd 多项验证规则
{getFieldDecorator(key, {
initialValue: data ? data[key] : '',
rules: [{ required: itemProps.required,
message: itemProps.placeholder,
pattern: itemProps.pattern }, ...itemProps.rules],
})
// reducer
required: true,
placeholder: '请输入',
rules: [
{
pattern: /^[\u4e00-\u9fa5_a-zA-Z0-9]+$/,
message: '只能为中文,字母,数字',
},
{
pattern: /^[\u4e00-\u9fa5_a-zA-Z0-9]+$/,
message: '只能为中文,字母,数字',
},
],
多层解构赋值
const obj = {
pageStore: {
policyObj: {
policy: 1
}
}
}
const { pageStore: { policyObj: { policy: info } } } = obj;
console.log(info) // 1 相当于声明了info,且policy 赋值给 info
const { pageStore: { policyObj: { policy } } } = obj;
console.log(policy) // 1
三元表达式取值的两种写法
getFieldDecorator(key, key === 'practiceCertiEffectiveStop' ? {
initialValue: data && data[key] ? moment(data[key]) : moment('9999-12-31'),
rules: [
{ required: itemProps.required, message: itemProps.message },
],
} : {
initialValue: data && data[key] ? moment(data[key]) : null,
rules: [
{ required: itemProps.required, message: itemProps.message },
],
})
getFieldDecorator(key, {
// eslint-disable-next-line no-nested-ternary
initialValue: data && data[key] ? moment(data[key]) : (key ==='practiceCertiEffectiveStop' ? moment('9999-12-31') : null),
rules: [
{ required: itemProps.required, message: itemProps.message },
],
})
// bad
const foo = maybe1 > maybe2
? "bar"
: value1 > value2 ? "baz" : null;
// 分离为两个三目表达式
const maybeNull = value1 > value2 ? 'baz' : null;
// better
const foo = maybe1 > maybe2
? 'bar'
: maybeNull;
// best
const foo = maybe1 > maybe2 ? 'bar' : maybeNull;
文字超出三行显示...,鼠标放上显示全部内容
<span title={record.remark}
style={{ display: '-webkit-box', WebkitBoxOrient: 'vertical',WebkitLineClamp: '3', overflow: 'hidden', wordWrap: 'break-word', wordBreak: 'break-word', }}
>
{record.remark}
</span>
div {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4;
text-overflow: ellipsis;
word-wrap: break-word;
word-break: break-word;
overflow: hidden;
}
https://github.com/ant-design/ant-design/issues/13825
antd 表格设置width不起作用
时间戳转化BUG
在本地时间转化为时间戳的时候,要使用/,如用new Date('2019-11-4 23:59:59')的时候,在PC端没有问题,但是手机端会出现报错。
const endTime = new Date('2019/11/4 23:59:59');
git相关问题
之前升级下了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
属性
第一种办法是常见的 将真实的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输入框设置为flex:1,希望input的宽度是所剩下的长度,结果是它比所剩下的长度要大,验证码这三个字就显示成两行了
原因是:input兼容弹性盒子有问题,它会有一个自己默认的最小长度,所以会导致验证码显示成两行
解决办法:我们可以给input输入框加一个div父元素,然后这个div设置flex:1,input设置width:100%;即可解决问题
react中的事件对象event中target在控制台查看为null,但是event.target却能获取到目标元素,为什么?
这是因为React里面的事件并不是真实的DOM事件,而是自己在原生DOM事件上封装的合成事件。
合成事件是由事件池来管理的,合成事件对象可能会被重用,合成事件的所有属性也会随之被清空。所以当在异步处理程序(如setTimeout等等)中或者浏览器控制台中去访问合成事件的属性,有可能就是空的。
上面的答案中给出的方案:event.persist(),其实就是将当前的合成事件从事件池中移除了,所以能够继续保有对该事件的引用以及仍然能访问该事件的属性。
react父组件调用,子(孙)组件的方法
export default class Parent extends Component {
render() {
return(
<div>
<Child onRef={this.onRef} />
<button onClick={this.click} >click</button>
</div>
)
}
onRef = (ref) => {
this.child = ref
}
click = (e) => {
this.child.myName()
}
}
class Child extends Component {
componentDidMount(){
this.props.onRef(this)
}
myName = () => alert('xiaohesong')
render() {
return ('woqu')
}
}
解决IOS8 或者安卓4.4 es6 转换报错。
利用getValueFromEvent 再输入的时候可以做很多操作,比如去除空格什么的,比在onblur里面写要方便很多
<Form.Item
key="libName"
label="险种名称"
>
{getFieldDecorator(`data[${val}].libName`, {
initialValue: '',
getValueFromEvent: (event) => {
return event.target.value.trim();
},
})(
<Input />,
)}
</Form.Item>
当使用了PureComponent时,要格式注意,如果页面中有浅比较,设置setState不会触发render的执行,即数据虽然变了但页面不会更新。
// 类似这种数据,不会触发更新
fruit: [{
type: 'bannana',
count: 0
},{
type: 'apple',
count: 0
}]
fruit.splice(0, 1);
this.setState({
fruit,
})
// 解决办法,深拷贝fruit操作,或者页面不要使用 PureComponent
解决办法: 使用深拷贝,或者页面不要使用 PureComponent
VSCODE 启用本地服务,安装 npm install http-server -g ,启动 http-server 即可。
类似这种多表格验证的,最好是使用如下的方法
声明两个数组, 一个数组 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阶段不更新踩坑,以及修改表单值方法。
参考 Ant Design的表单onChange阶段不更新踩坑,以及修改表单值方法_何其涛的博客-CSDN博客_antd form onchange
antd 日期组件 (选择范围 大于等于开始时间,小于等于结束时间)。大于等于开始时间很简单,结果小于等于结束时间试了半天才知道endOf('day')就可以了
多看文档 Moment.js | Docs
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();
}
antd表单中的validateFields没有被执行可能的问题及解决_照物华的博客-CSDN博客_react validatefields
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先触发,即便同时绑定。)
楼主说的情况不是事件冲突,⽽是⻚⾯结构变化导致绑定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>
总结一句话, 资源文件同域下载,跨域优先打开,打不开就下载。
sort实现数组内对象排序
/**
* @description: 根据数组内对象某一属性(number类型)进行排序
* @param {*} source 目标数组
* @param {*} sortField 排序属性
* @param {*} sortType ASC DESC 默认升序
* @return {*}
*/
const sortFn = (source, sortField, sortBy = 'ASC') => {
return source.sort((a, b) => sortBy === 'ASC' ? a[sortField] - b[sortField] : b[sortField] - a[sortField]);
}
移动端键盘弹出没有顶起页面可以配置如下属性
form滚动到校验未通过位置