工作中积累的代码优化,技术栈react、组件antd,工具underscore(自用可参考,不定期更新)

本文分享了代码优化的经验,包括判断条件的精简、模块化与组件化思想、请求参数和返回数据处理的技巧,以及如何封装和复用代码。探讨了代码简洁性、异常处理、样式管理、数据验证等方面,提供了提升代码质量和效率的实用建议。
摘要由CSDN通过智能技术生成

这块儿经验来自于代码优化

判断条件学会精简
  • 判断条件不同结果相同可以使用&&连接
  • 判断条件满足其中之一可以使用||
  • 能够合并的代码就要合并
// 合并之前
if(a.length > 20 && name === 'name') {
	message.error('名称不能超过20字')
} else if(a.length > 20 && name === 'prename') {
	message.error('预览名称不能超过20字')
} else { ... }
// 合并之后
if(a.length > 20 && (name === 'name' || name === 'prename' )) {
	message.error('名称或者预览名称不能超过20字')
}  else { ... }
模块化,组件化思想
  • 请求参数和返回数据处理差不多的情况下就要学会合并,譬如:新增和修改可以共用一个方法,req、url和提示语可以根据类型来定义,另外req请求多传参数也不会影响后端处理;
  • 发送请求前的数据验证可以单独封装一个函数来处理,可以参考管理员管理模块的新增和修改;
// 在Com组件中
static validWhenAddOrUpdate(state) {
		if (!state.userId) {
			message.error('账号ID不能为空');
			return false
		}
		if (state.userId.search(' ') !== -1) {
			message.error('账号ID不能带有空格(前面,中间,后面都不行)');
			return false
		}
		if (!state.userName) {
			message.error('账号姓名不能为空');
			return false
		}
		if (!state.department) {
			message.error('所属部门不能为空');
			return false
		}return false
		}
		return true;
	}

//使用的地调用
	handleOkNew = () => {
		const thisNewState = this.new.state;
		if (!Com.validWhenAddOrUpdate(thisNewState)) {
			return;
		}
	}
  • 样式需放到css里面,统一管理
  • 合理使用参数,就可以与其他组件公用一个方法
基础知识要过关
  • map改变原数组不需要return,如果是使用循环则使用forach或者_.each
  • 该单独写的函数需单独写,避免函数中嵌套函数,函数要做到小而细
  • 封装的函数注意函数的调用时机
  • 变量使用es6的let或者const(常亮使用const定义)
要学会处理异常数据
  • 接收数据时先做好可能判断,避免在html中写js代码,否则会因为数据不规范导致页面崩溃(所以可以提前定义变量,html只负责渲染)
  • 判断数据最好先设置一个空数据,在对数据进行处理,合理利用三目运算判断,如果判断条件与第一种可能相同可以使用||符号

学会代码简洁,复用、使用扩展运算符等

  • // fixme:可以在config中设置一个初始条件,使用扩展符(...)的方式加载进来,同时方便重置的时候直接使用

  • 最开始可以设置一个初始值,把需要传递的req设置到一个对象中

  • getReq = () => {
    		let conditionObj = this.state.conditionObj;
    		let request = {
    			customerTypes: conditionObj.clientType,
    			investDurationType: conditionObj.deadline,
    			netValue: conditionObj.product,
    			openType: conditionObj.openType,
    			productObject: conditionObj.productObject,
    			productTypes: conditionObj.productType,
    			raiseWays: conditionObj.raise,
    			saleDateEnd: conditionObj.saleEndDate,
    			saleDateStart: conditionObj.saleStartDate,
    			specialFieldType: conditionObj.special,
    			startPointType: conditionObj.investment,
    		};
    		return request;
    	};
    
  • 在需要的地方引入,在可以添加其他键值对

  • 在state中存入一个reqObj专门用来最为发请求的对象,以便后面的接口调用

  • 之后需要调用可以直接利用es6的扩展运算符进行copy

动态渲染表格数据
				this.setState({loading: false});
				let cnt = res.content ? res.content : {}, dataSource = [];
				let columns = [
					{
						title: '渲染的时间',
						dataIndex: 'date',
						width: 200,
						align: 'center',
						fixed: 'left',
					}
				];
				_.each(cnt.date, (item) => {
					dataSource.push({date: item})
				});
				_.each(cnt.data, (val, key) => {
					let column = {
						title: key,
						dataIndex: key,
						width: 140,
						align: 'center',
					};
					if (key === '需要固定的值') {
						column.fixed = 'left'
					}
                    // 根据length判断表格宽度
					if (key.length > 4) {
						column.width = 200
					}
                    // 整理dataSourece,根据后台返回数据返回数据整理,并添加key值
					_.each(dataSource, (item, i) => {
						item[key] = number(val[i], 2);
						item.key = i;
					});
					columns.push(column);
				});
				let tableWith = calculate(columns);
				if (tableWith < this.state.width - 200) {
					_.each(columns, (item, i) => {
						delete item.fixed
					});
				}

				this.setState({dataSource, columns, totalModal: cnt.total});
注意熟悉规范,小细节,知识点
  • // fixme: 代码引入顺序按照 第三方库-公共方法-公共组件-各模块配置;每个 import 以分号结尾;删除未使用的引入
  • 数据都要考虑为空,不存在,undefined等情况。特别是使用js中的方法
    • 未判断数据,导致toFixed报错(可以用三目或者使用number方法转换)
    • 直接取对象数组中的值,可能会存在找不到对应key值而报错
    • res中的返回值吗,不能绝对信任,都应加上||判断
    • props中传值也需对传递过来要使用的值进行验证,否则直接进行split划分会报错
    • map对数据格式要求严格,如果不是数组也会报错(可以使用underscore中的_.map,或者使用判断,或者使用三目不存在就为[])
从别人代码中获取经验
  • 自定义数组,遍历展示

  • render: (val) => {
    	let item = _.find(whether, (item) => {
    		return item.value === val
    	});
    	let text = item ? item.label : '';
    		return <span>{text}</span>
    	}
    export const whether = [
    	{label: '不限', value: ''},
    	{label: '是', value: '1'},
    	{label: '否', value: '0'},
    ];
    // 方法封装直接根据对象数组中的value取出相应label中的值
    export const getLabel = (map, v,name= 'label',val='value') => {
    		// 注:Number会将null值转换为0,所以你的值中有0会被错误转换
      	//const res = _.find(map, item => Number(item[val]) === Number(v));
      	// 改造之后
      	const res = _.find(map, item => {
      		v || v === 0 ? Number(item[val]) === Number(v)) : ''
      	}';
      	return res ? res[name] : '--'; 
      }
    
  • 表格中增加tips(表格中有排序,有其他hover效果)

  • filterDropdown: true,
    	filterIcon: () => {
    		return (
    			<Tooltip placement="top" overlayClassName={'data-table'}>
    				<Icon type="question-circle" theme="outlined"/>
    			</Tooltip>
    		);
      }
    
  • 在table表格中配置

  • locale={{
       filterTitle: '鼠标hover时显示的文字',
    }}
    
  • 就可以在页面中显示

antd中select搜索遇到的问题

  • 复现:1.select组件中的value和选项中的value值相同才能复现,特别注意value的数据类型,number or string
  • 复现:2.如果option中的数据是动态渲染的,需要保证数据来源的数组中有该条数据
list.map(val => (
	<Option key={val.key} value={val.key}>{val.name}</Option>
))
  • 搜索 即使你绑定了其他函数对list进行改变,输入的值会根据option中的value进行搜索展示。如果使用名字对list进行搜索,需将代码改为
list.map(val => (
	<Option key={val.key} value={val.value}>{val.name}</Option>
))

根据表格中每项数据显示的时间判断展示内容是否可点

let  flag ;
 flag = item.pushStatus === 1 && moment()<moment(item.pushTime);
item.flag = flag;
return (<div>
	{item.pushStatus === 0 ? releaseUp : (item.flag || item.pushStatus === 2 ? releaseDown : ' 下线 ')}
	{item.pushStatus === 0 ? update : ' 修改 '}
	{item.pushStatus === 0 ? remove : ' 删除'}
</div>)
ES6的活学活用
  • 扩展运算加结构赋值
    this.setState({ ... item })
  • 报错
    this.setState is not a functionat Object.handleChange [as dateCheck]
  • 解决
    注意this指向问题,是不是直接使用的function a () {}
    建议使用箭头函数 () => {}

下拉单选

<Select
							value={thisState.moduleId}
							style={{width:157}}
							size="small"
							onChange={(val) => this.handleChange(val, 'moduleId')}
						>
							<Option value="" disabled>请选择</Option>
							{ _.map(thisState.moduleList, item => <Option value={item.moduleId + ''} key={item.moduleId}>{item.moduleName}</Option>)}
						</Select>

1.在Select中添加固定

添加getPopupContainer={triggerNode => triggerNode.parentNode},使其固定在父元素中

2.在DatePicker中添加固定

添加getCalendarContainer={triggerNode => triggerNode.parentNode},使其固定在父元素中

3.input框绑定中文事件

  • compositionstart是input框中自带的事件,当输入法为中文时,在input框中输入触发该事件

  • compositionend当输入时按空格,或者input框失去焦点,或者删除输入的内容时会触发该事件

4.underscore中_.isEmpty()

  • 返回的是一个布尔值

  • 可用于判断复杂数据类型是否为空

_.isEmpty([]);
=> true
_.isEmpty([1, 2, 3]);
=> false
_.isEmpty({});
=> true
_.isEmpty({1,2,3});
=> false
  • 判断基本数据类型基本为true,除了含内容的字符串(‘不是空的字符串都可以’)
_.isEmpty('');
=> true
_.isEmpty(undefined);
=> true
_.isEmpty(null);
=> true
_.isEmpty(123);
=> true
_.isEmpty(false);
=> true

//这俩有点特殊
_.isEmpty(true);
=> true

_.isEmpty('aaa');
=> false

直接if判断

//
if('aa') {
    console.log("'aa'为true");
  }
 if(123) {
    console.log("123为true");
  }

// 这些不展示
   if('') {
    console.log("这条不展示");
  }
  if(null) {
    console.log("null为false");
  }
  if(undefined) {
    console.log("undefined为false");
  }

echarts中饼图大小位置调整

在series中设置

radius: '60%', // 半径
center: ['50%', '40%'], //左右上下的距离
几个特殊的转译
此时会把布尔类型的值转换为数字类型 true=1 false=0
  • 2 == true; // false
  • (!!2 == true); // true
  • (!!0 == true); // false
  • (!![] == true); // true
  • (!!‘0’ == true); // true
!是表示非,能把数据类型转换为布尔类型
  • 0 == false; // true
  • 0 == ‘’; // true
  • NaN == NaN; // false
  • [] == false; // true
  • [] == ![]; // true
减号,Number转换为数字
  • null - 0; //0
  • Number(null) // 0
第三方工具,用于组件之前通信,不受高阶组件影响(PubSub)

参考链接:https://www.cnblogs.com/lcosima/p/8626491.html

pubsubjs源码及使用详情:https://github.com/mroderick/PubSubJS

发送消息:PubSub.publish(名称,参数)

订阅消息:PubSub.subscribe(名称,函数)

取消订阅:PubSub.unsubscrib(名称)

a.首先引入包,在需要发送消息的位置,进行如下设置

PubSub.publish('PubSubmessag',this.state.increase);  

b.订阅消息在要获获取值,或者要触发函数的地方使用如下方法

  • 订阅消息PubSub.subscribe(名称,函数)中的函数有两个参数,分别对应发送消息PubSub.publish(名称,参数)中的名称和参数
PubSub.subscribe('PubSubmessage',(topic,message) => console.log(topic,message)
                 
componentDidMount(){ 
    //整体返回的值进行取消订阅
  this.pubsub_token = PubSub.subscribe('PubSubmessage',(topic,message) => {  
    this.setState({  
      increase: message  
    });  
  });  
}  

c.使用PubSub.unsubscrib()取消订阅消息

componentWillUnmount(){  
  PubSub.unsubscribe(this.pubsub_token);  
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值