ctrl+c и ctrl+v приносят нам много удобства, но также делают нас ленивыми и нежелающими думать.
1. Введение
Я считаю, что многие люди похожи на меня.При разработке проекта это происходит потому, что проект торопится, или это неожиданно, и по другим причинам. Частое использование Ctrl+C и Ctrl+V приводит к большому количеству повторяющегося кода. За последние несколько дней я также прочитал написанный ранее код, кратко изучил его, выбрал несколько примеров и поделился тем, как улучшить возможность повторного использования кода с целью обеспечения качества кода в определенных сценариях.
Чтобы улучшить возможность повторного использования кода, должны быть разные сценарии и разные решения. В то же время качество кода также должно быть гарантировано. Не рекомендуется принудительно улучшать повторное использование кода.Если повторное использование кода будет улучшено, удобочитаемость и ремонтопригодность кода значительно снизятся, и выигрыш может не стоить потери.
2.HTML+CSS
При работе над проектом я считаю, что на странице всегда будет много похожих кнопок, таких как следующая картинка, несколько похожих кнопок на проекте. Столкнувшись с таким спросом, я сразу написал три кнопки.
<button type="button" class='u-btn-yes-samll'>确定</button>
<button type="button" class='u-btn-yes'>确定</button>
<button type="button" class='u-btn-yes-big'>确定</button>
css
button{
border:none;
font-family:'微软雅黑';
}
.u-btn-yes{
width:80px;
height:36px;
font-size:14px;
color:#fff;
border-radius:10px;
background:#09f;
}
.u-btn-yes-samll{
width:60px;
height:30px;
font-size:12px;
color:#fff;
border-radius:10px;
background:#09f;
}
.u-btn-yes-big{
width:100px;
height:40px;
font-size:16px;
color:#fff;
border-radius:10px;
background:#09f;
}
Это равносильно добавлению нескольких строк кода css для каждой дополнительной кнопки, фактически изменяются только три свойства: ширина, высота и размер шрифта.
Повторное использование кода на самом деле может быть выполнено в зависимости от размера.
.u-btn-yes{
width:80px;
height:36px;
font-size:14px;
color:#fff;
border-radius:10px;
background:#09f;
}
.u-btn-yes.u-btn-samll{
width:60px;
height:30px;
font-size:12px;
}
.u-btn-yes.u-btn-big{
width:100px;
height:40px;
font-size:16px;
}
пейджинговый вызов
<button type="button" class='u-btn-yes u-btn-samll'>确定</button>
<button type="button" class='u-btn-yes'>确定</button>
<button type="button" class='u-btn-yes u-btn-big'>确定</button>
На странице может быть много похожих кнопок, но различные цвета (как показано на рисунке ниже) также можно гибко обрабатывать, чтобы их можно было свободно комбинировать. Это также способ, которым пользуются многие библиотеки пользовательского интерфейса в сообществе.
.u-btn{
width:80px;
height:36px;
font-size:14px;
color:#fff;
border-radius:10px;
background:#09f;
}
.u-btn-samll{
width:60px;
height:30px;
font-size:12px;
}
.u-btn-big{
width:100px;
height:40px;
font-size:16px;
}
.u-btn-red{
background:#f33;
}
.u-btn-yellow{
background:#f90;
}
html
<button type="button" class='u-btn u-btn-samll'>确定</button>
<button type="button" class='u-btn u-btn-red'>确定</button>
<button type="button" class='u-btn u-btn-big u-btn-yellow'>确定</button>
Для этих кнопок не рекомендуется задавать margin, positon и другие стили, т.к. разные кнопки находятся в разных местах, вышеперечисленные свойства принципиально разные.
3.JavaScript
Что касается преимуществ повторного использования кода, то в приведенном выше примере HTML+CSS нет очевидных преимуществ, но преимущества улучшения повторного использования кода в JS более очевидны.Вот несколько примеров.
3-1. Инкапсулируйте общие функции
Такой код есть в предыдущем проекте компании, и цель тоже очевидна: когда пользователь заполняет форму, она отправляется до того, как она будет заполнена, фронтенд должен выдать простую подсказку.
//当信息没填写完整的时候弹出提示
layer.alert('请检查信息是否填写完整',{
title:'提示',
icon:2
})
Судя по слою библиотеки с открытым исходным кодом, код выглядит очень просто. Однако с развитием проекта у пользователей появилось несколько мест для заполнения формы, поэтому приведенный выше код будет скопирован в несколько мест, что неизбежно будет немного избыточным.
Кроме того, одна из самых больших проблем с этим заключается в следующем: если приведенный выше код используется в 20 местах проекта, и однажды требования меняются, значение атрибута title должно измениться с «подсказка» на «предупреждение». Это было бы хлопотно, найти 20 мест, даже если в редакторе есть функция глобальной замены, вероятность таких изменений относительно высока. столкнуться с такой ситуацией. Предыдущий метод заключается в простой и грубой инкапсуляции этого всплывающего окна, удобного для повторного использования.
function openTips(){
//当信息没填写完整的时候弹出提示
layer.alert('请检查信息是否填写完整',{
title:'提示',
icon:2
});
}
Просто вызывайте его, когда вам это нужно, где вам это нужно, так что вы можете написать намного меньше кода! Чтобы изменить его, вам нужно только изменить место openTips, и все готово.
openTips();
3-2. Используйте режим стратегии вместо переключателя
Давайте посмотрим на другой пример. Заимствуйте код, присланный предыдущими друзьями группы.
Данные моделирования
let listWarnConf = [
{
warnType: 1,
warnCondition: 220,
},
{
warnType: 2,
warnCondition: 36,
},
{
warnType: 3,
warnCondition: 45,
},
{
warnType: 4,
warnCondition: 110,
},
{
warnType: 5,
warnCondition: 380,
}
]
код бизнес-логики
listWarnConf.forEach(item => {
switch(item.warnType) {
case 1:
item.warnTypeText = '超压';
item.warnConditionText = `电压高于${item.warnCondition}V`
break;
case 2:
item.warnTypeText = '欠压';
item.warnConditionText = `电压低于${item.warnCondition}V`
break
case 3:
item.warnTypeText = '超载';
item.warnConditionText = `电流高于${item.warnCondition}A`
break
case 4:
item.warnTypeText = '电压不平衡';
item.warnConditionText = `电压不平衡高于${item.warnCondition}%`
break
case 5:
item.warnTypeText = '电流不平衡';
item.warnConditionText = `电流不平衡${item.warnCondition}%`
break
}
})
Это нормально смотреть на результат таким образом, но глядя на такое количество случаев, это все операции присваивания. И самая большая проблема та же, что и выше. Если он используется в нескольких местах и требования меняются, так много мест все еще необходимо изменить. Следующие оптимизации улучшат возможность повторного использования кода.
//设置配置数据
let warnConfig={
1:{
warnTypeText:'超压',
warnConditionText:'电压高于replaceTextV'
},
2:{
warnTypeText:'欠压',
warnConditionText:'电压低于replaceTextV'
},
3:{
warnTypeText:'超载',
warnConditionText:'电流高于replaceTextV'
},
4:{
warnTypeText:'电压不平衡',
warnConditionText:'电压不平衡高于replaceText%'
},
5:{
warnTypeText:'电流不平衡',
warnConditionText:'电流不平衡高于replaceText%'
}
}
//业务逻辑--根据配置数据设置warnTypeText和warnConditionText
listWarnConf.forEach(item => {
item.warnTypeText=warnConfig[item.warnType].warnTypeText;
item.warnConditionText=warnConfig[item.warnType].warnConditionText.replace('replaceText',item.warnCondition);
})
Таким образом, количество изменений в коде не уменьшилось, а читаемость хуже, чем у переключателя, но читается. Но это приводит к менее повторяющемуся коду, а данные конфигурации и бизнес-логика разделены.Если вы хотите изменить данные конфигурации или бизнес-логику в будущем, просто измените один из них, не затрагивая друг друга. Извлеките данные конфигурации для общего пользования, а затем, когда вам нужно изменить их, просто измените их напрямую.
Что касается улучшения возможности повторного использования кода или сокращения повторяющегося кода, я лично считаю, что могу работать над достижением следующих целей: когда требования меняются и код необходимо модифицировать, один и тот же код не следует модифицировать дважды.
3-3. Сохраняйте функции с единой ответственностью и гибкой комбинацией
Сохраняйте единую ответственность функции, убедитесь, что функция выполняет только одно действие, каждое действие не влияет друг на друга и может свободно комбинироваться, что может улучшить повторное использование кода.
Например, в следующем коде данные заказа, запрашиваемые с сервера, выглядят следующим образом, и требуется следующая обработка. 1. Отображение соответствующего значения в соответствии со статусом (0-выполняется, 1-завершено, 2-порядок ненормальный) 2. Отображать startTime из метки времени как гггг-мм-дд 3. Если значение поля представляет собой пустую строку, установите для значения поля значение «--».
let orderList=[
{
id:1,
status:0,
startTime:1538323200000,
},
{
id:2,
status:2,
startTime:1538523200000,
},
{
id:3,
status:1,
startTime:1538723200000,
},
{
id:4,
status:'',
startTime:'',
},
];
Требования кажутся простыми, а код минимальным.
let _status={
0:'进行中',
1:'已完成',
2:'订单异常'
}
orderList.forEach(item=>{
//设置状态
item.status=item.status.toString()?_status[item.status]:'';
//设置时间
item.startTime=item.startTime.toString()?new Date(item.startTime).toLocaleDateString().replace(/\//g,'-'):'';
//设置--
for(let key in item){
if(item[key]===''){
item[key]='--';
}
}
})
Работающий результат тоже нормальный, но написание кода таким образом будет очень повторяющимся.Например, следующее, другой набор пользовательских данных, запрошенный тяжелым сервером, пользовательские данные не имеют статуса, startTime, два поля и пользовательский личность должна отображаться в соответствии с типом (0-обычный пользователь, 1-вип, 2-супер вип).
let userList=[
{
id:1,
name:'守候',
type:0
},
{
id:2,
name:'浪迹天涯',
type:1
},
{
id:3,
name:'曾经',
type:2
}
]
Когда возникает такой спрос, написанный ранее код нельзя использовать повторно, а можно только копировать и модифицировать.
let _type={
0:'普通用户',
1:'vip',
2:'超级vip'
}
userList.forEach(item=>{
//设置type
item.type=item.type.toString()?_type[item.type]:'';
//设置--
for(let key in item){
if(item[key]===''){
item[key]='--';
}
}
})
Результат нормальный, предположительно все нашли проблему, код немного избыточен. Давайте воспользуемся принципом единой ответственности, чтобы преобразовать функцию операции и установить статус, время начала, тип, -- . Это разделено на четыре функции.
let handleFn={
setStatus(list){
let _status={
0:'进行中',
1:'已完成',
2:'订单异常'
}
list.forEach(item=>{
item.status=item.status.toString()?_status[item.status]:'';
})
return list
},
setStartTime(list){
list.forEach(item=>{
item.startTime=item.startTime.toString()?new Date(item.startTime).toLocaleDateString().replace(/\//g,'-'):'';
})
return list;
},
setInfo(list){
list.forEach(item=>{
for(let key in item){
if(item[key]===''){
item[key]='--';
}
}
})
return list;
},
setType(list){
let _type={
0:'普通用户',
1:'vip',
2:'超级vip'
}
list.forEach(item=>{
item.type=item.type.toString()?_type[item.type]:'';
})
return list;
}
}
Просто вызовите функцию непосредственно ниже
//处理订单数据
orderList=handleFn.setStatus(orderList);
orderList=handleFn.setStartTime(orderList);
orderList=handleFn.setInfo(orderList);
console.log(orderList);
//处理用户数据
userList=handleFn.setType(userList);
userList=handleFn.setInfo(userList);
console.log(userList);
Результат тоже нормальный
Если вам не нравятся проблемы с непрерывным присваиванием, вы можете позаимствовать идею jQuery и сделать цепочку вызовов.
let ec=(function () {
let handle=function (obj) {
//深拷贝对象
this.obj=JSON.parse(JSON.stringify(obj));
};
handle.prototype={
/**
* @description 设置保密信息
*/
setInfo(){
this.obj.map(item=>{
for(let key in item){
if(item[key]===''){
item[key]='--';
}
}
});
return this;
},
/**
* @description 设置状态
*/
setStatus(){
let _status={
0:'进行中',
1:'已完成',
2:'订单异常'
}
this.obj.forEach(item=>{
item.status=item.status.toString()?_status[item.status]:''
});
return this;
},
/**
* @description 设置时间
*/
setStartTime(){
this.obj.forEach(item=>{
item.startTime=item.startTime.toString()?new Date(item.startTime).toLocaleDateString().replace(/\//g,'-'):'';
});
return this;
},
/**
* @description 设置type
*/
setType(){
let _type={
0:'普通用户',
1:'vip',
2:'超级vip'
}
this.obj.forEach(item=>{
item.type=item.type.toString()?_type[item.type]:'';
})
return this;
},
/**
* @description 返回处理结果
* @return {Array|*}
*/
end(){
return this.obj;
}
}
//暴露构造函数接口
return function (obj) {
return new handle(obj);
}
})();
Это может быть связано
//处理订单数据
orderList=ec(orderList).setStatus().setStartTime().setInfo().end();
console.log(orderList);
//处理用户数据
userList=ec(userList).setType().end();
console.log(userList);
Дело вот в чем, я считаю, что все обнаружили, что очень серьезная проблема в том, что количество циклов увеличилось. Перед оптимизацией вам нужно только один раз зациклиться, вы можете установить состояние, установить время, установить - эти шаги завершены, но теперьsetStatus().setStartTime().setInfo()
Код здесь каждый раз, когда функция выполняется, проходит через массив один раз, и это необходимо оптимизировать. Способ обработки заключается в том, что в каждой функции записывается только то, что должно быть обработано, но не обрабатывается, когда оно будет выполнено до конца, оно будет обработано равномерно и возвращено.
let ec=(function () {
let handle=function (obj) {
//深拷贝对象
this.obj=JSON.parse(JSON.stringify(obj));
//记录要处理的步骤
this.handleFnList=[];
};
handle.prototype={
/**
* @description 设置保密信息
*/
handleSetInfo(item){
for(let key in item){
if(item[key]===''){
item[key]='--';
}
}
return this;
},
setInfo(){
this.handleFnList.push('handleSetInfo');
return this;
},
/**
* @description 设置状态
*/
handleSetStatus(item){
let _status={
0:'进行中',
1:'已完成',
2:'订单异常'
}
item.status=item.status.toString()?_status[item.status]:''
return item;
},
setStatus(){
this.handleFnList.push('handleSetStatus');
return this;
},
/**
* @description 设置时间
*/
handleSetStartTime(item){
item.startTime=item.startTime.toString()?new Date(item.startTime).toLocaleDateString().replace(/\//g,'-'):'';
return item;
},
setStartTime(){
this.handleFnList.push('handleSetStartTime');
return this;
},
/**
* @description 设置type
*/
handleSetType(item){
let _type={
0:'普通用户',
1:'vip',
2:'超级vip'
}
item.type=item.type.toString()?_type[item.type]:'';
return item;
},
setType(){
this.handleFnList.push('handleSetType');
return this;
},
/**
* @description 返回处理结果
* @return {Array|*}
*/
end(){
//统一处理操作
this.obj.forEach(item=>{
this.handleFnList.forEach(fn=>{
item=this[fn](item);
})
})
return this.obj;
}
}
//暴露构造函数接口
return function (obj) {
return new handle(obj);
}
})();
Таким образом, предыдущий вызывающий метод не нужно менять, и тогда результат правильный.
Может быть, все думают, что очень простое требование, но оно такое сложное. Если это правильно, потому что это действительно сложно и читаемость плохая, но я думаю, что обработка данных, с которыми сталкивается проект, не только это, но и формат отображения суммы, и анализ и отображение различных кодов состояния других данных. , номер банковской карты делится через каждые 4 цифры, отображение номера телефона и тд. Так что просто сначала инкапсулируйте его, а потом используйте напрямую. Я не знаю, горько ли это? Если требования относительно просты, инкапсуляция таким образом может и не понадобиться.
4. Резюме
Это краткое изложение чтения кода во время отпуска и улучшения повторного использования кода.Конечно, есть несколько примеров, но они были написаны ранее, и они похожи на примеры, упомянутые в этой статье, поэтому я не буду их снова упоминать. Улучшение возможности повторного использования кода — это большая тема. Если у вас есть хорошие предложения или примеры, поделитесь ими.
------------------------- Великолепная разделительная линия --------------------
Если вы хотите узнать больше, общаться со мной и продвигать вакансии, добавьте меня в WeChat. Или обратите внимание на мой паблик WeChat: В ожидании книжного магазина