Савјети и трикови за стварање корисничких УИ компоненти за вишекратну употребу

Фотограф Фарзард Назифи

У овом чланку желим да поделим неколико савета и трикова које користим док правим нашу основну библиотеку фронтенда помоћу Ембер.јс. Без контакта с њим раније, то је била сјајна прилика за учење. Надам се да ћете уживати! Имајте на уму да код коришћен за објашњење идеја у чланку садржи само довољно информација да бисте добили поен преко. Такође користи одређену терминологију Ембер.јс, али концепти би требали бити оквирно-агностички.

Објективи - Задаци

Једноставно речено, услови за изградњу библиотеке су следећи:

  1. Мора бити продуктивна.
  2. То мора бити одрживо.
  3. Мора бити доследан.

Приступи

Смањите пословну логику

Један од најчешћих проблема са којима се сусрећем на пројектима су компоненте које у њима садрже превише логике. Дакле, обављање задатака који су теоретски изван њиховог обима.

Пре примене било које функционалности, добро је навести неке дужности за које је одговорна компонента.

Замислите да правимо компоненту дугмета.

Желео бих да могу:

  • Обавестите о којој се врсти дугмета ради - Примарно или редовно
  • Информишите садржај приказан унутар дугмета (икона и текст)
  • Онемогућите или омогућите дугме
  • Извршите неку радњу након клика

Имајући овај мали обрис, раздвојите различите делове који су укључени у процес изградње ове компоненте. Покушајте да идентификујете где се ствари могу сместити.

1 - Тип и садржај су специфични за компоненте, тако да се могу сместити у датотеку компонената.

Будући да је тип - у одређеној мери - потребан, додајмо верификацију у случају да није дата вредност.

цонст типе = гет (ово, 'типе');
цонст врсте = {
  примарни: 'бтн - примарни',
  регулар: 'бтн - редовно',
}
ретурн (тип)? врсте [тип]: типе.регулар;

Свиђа ми се пресликавање својстава у објект јер омогућава да се ствари скалирају без већег напора - у случају да нам затреба дугме за опасност или нешто слично.

2 - Онемогућено стање се може наћи на различитим компонентама попут улаза. Да би се избегло понављање, ово понашање се може преместити у модул или било коју заједничку структуру - људи га зову миксин.

3 - Радња клика се може пронаћи у различитим компонентама. Дакле, такође се може преместити у другу датотеку и не би требало садржавати логику унутар ње - једноставно позивање повратног позива који је дао програмер.

На овај начин можемо имати представу у којим случајевима се наша компонента треба бавити истовремено помажући да се нацрта основна архитектура која подржава проширење.

Одвојено корисничко сучеље за вишекратну употребу

Одређене интерактивне интеракције су уобичајене међу различитим компонентама, као што су:

  • Омогући / онемогући - нпр. тастери, улази
  • Прошири / смањи - нпр. колапс, падајуће листе
  • Прикажи / сакриј - поприлично све

Ова својства се често користе само за контролу стања вида - надамо се.

Одржавајте доследну номенклатуру у различитим компонентама. Све акције везане за визуелно стање могу се преместити у микс.

/ * УИСтатеМикин * /
онеспособити () {
  сет (ово, 'онемогућено', истина);
  врати ово;
},
енабле () {
  сет (ово, 'онеспособљено', лажно ');
  врати ово;
},

Свака метода је одговорна само за пребацивање одређене променљиве и враћа тренутни контекст за везивање, као што су:

дугме
  .дисабле ()
  .сховЛоадингИндицатор ();

Овај приступ се може проширити. Може да прихвати различите контексте и контролише спољне променљиве уместо да користи интерне. На пример:

_гетЦуррентДисабледАттр () {
  ретурн (исПресент (гет (ово, 'онеспособљено')))
    ? 'онеспособљено' / * Вањски параметар * /
    : 'је онемогућен'; / * Интерна променљива * /
},
омогућити (контекст) {
  сет (контекст || ово, ово._гетЦуррентДисабледАттр (), лажно);
  врати ово;
}

Ограничење функционалности базе

Свака компонента садржи одређене рутине. Ове рутине морају бити изведене без обзира на сврху компоненте. На примјер, провјеравање повратног позива прије покретања.

Ове подразумеване методе се такође могу преместити у сопствене комбинације:

/ * БасеЦомпонентМикин * /
_исЦаллбацкВалид (цаллбацкНаме) {
  цонст цаллбацк = гет (ово, цаллбацкНаме);
  
  ретурн !! (исПресент (повратни позив) && типеоф цаллбацк === 'функција');
},
_хандлеЦаллбацк (повратни позив, параме) {
  иф (! тхис._исЦаллбацкВалид (повратни позив)) {
    баци нову грешку (/ * порука * /);
  }
  тхис.сендАцтион (повратни позив, парамс);
},

А затим укључени у компоненте.

/* Саставни део */
онЦлицк (парамс) {
  тхис._хандлеЦаллбацк ('онЦлицк', парамс);
}

Ово одржава вашу основну архитектуру доследном. Такође омогућава проширење, па чак и интеграцију са софтвером других произвођача. Али молим вас, немојте бити филозофирајући апстрактно.

Састављање компонената

Избегавајте функционалност преписивања колико год можете. Специјализација се може постићи. Може се постићи саставом и груписањем. Као и спајање мањих компоненти заједно како би се створили нови елементи.

На пример:

Основне компоненте: Дугме, падајући мени, улаз.
Дугме за спуштање => дугме + падајући
Аутоматско довршавање => унос + падајући
Изаберите => улаз (само за читање) + падајући мени

На овај начин свака компонента има своје задатке. Свака обрађује своје стање и параметре док компонента омота обрађује своју специфичну логику.

Раздвајање брига у најбољем реду.

Подјела забринутости

Када састављате сложеније компоненте, постоји могућност поделе проблема. Можете поделити забринутости између различитих делова компоненте

Рецимо да градимо одабрану компоненту.

{{образац за одабир форума = предметиИИДИ = предмети}}
итемс = [
  {десцриптион: 'Производ бр. 1', вредност: 1},
  {десцриптион: 'Производ бр. 2', вредност: 2}
]

Интерно имамо једноставну улазну компоненту и падајући мени.

{{образац за унос облика = _ опис}}
{{уи-дропдовн итемс = предмети онСелецт = (акција 'селецтИтем')}}

Наш главни задатак је да кориснику представимо опис, али он за нашу апликацију нема значења - вредност заиста јесте.

Приликом одабира опције раздвајате објект, слањем описа на наш улаз путем интерне варијабле, истовремено гурајући вриједност до контролера, ажурирајући повезану варијаблу.

Овај се концепт може применити на компоненте у којима се везана вредност мора трансформисати, попут броја, аутоматског довршавања или одабраног поља. Датепицкери такође могу имплементирати ово понашање. Они могу уклонити датум прије ажурирања везане варијабле, а кориснику ће представити маскирану вриједност.

Ризици постају све већи како трансформације повећавају сложеност. Прекомерном логиком или пружањем подршке догађајима - размислите пре него што примените овај приступ.

Пресетс вс Нев Цомпонентс

Понекад је потребно оптимизирати компоненте и услуге да би се олакшао развој. Испоручују се у облику унапред подешених поставки или нових компоненти.

Унапред постављене поставке су параметри. Када су информисани, они постављају унапред одређене вредности на компоненти, поједностављујући њену декларацију. Међутим, нове компоненте су обично више специјализоване верзије основних компоненти.

Тешки део је знати када имплементирати унапред подешене поставке или креирати нове компоненте. При доношењу ове одлуке користим следеће смернице:

Када креирати унапред подешене вредности

1 - понављајући обрасци употребе

Постоје случајеви када се одређена компонента поново употребљава на разним местима са истим параметрима. У тим случајевима волим давати предност пресетима над новим компонентама, посебно када основна компонента има превелики број параметара.

/ * Редовна примена * /
{{образац-аутоматско довршавање
    везивање = продуцтИд
    урл = "производи" / * УРЛ за преузимање * /
    лабелАттр = "опис" / * Атрибут коришћен као ознака * /
    валуеАттр = "ид" / * Атрибут који се користи као вредност * /
    апиАттр = "производ" / * Парам послан на захтев * /
}}
/ * Пресетс * /
{{образац-аутоматско довршавање
    пресет = "производ"
    везивање = продуцтИд
}}

Вриједности из унапријед постављене вриједности постављају се само ако параметар није информиран, чувајући његову флексибилност.

/ * Наивна имплементација унапријед постављеног модула * /
цонст пресетс = {
  производ: {
    урл: 'производи',
    лабелАттр: 'опис',
    валуеАттр: 'ид',
    апиАттр: 'производ',
  },
}
цонст аттрс = пресетс [гет (ово, 'пресет')];
Објецт.кеис (аттрс) .форЕацх ((проп) => {
  иф (! гет (тхис, проп)) {
    сет (овај, проп, аттрс [проп]);
  }
});

Овај приступ смањује знање потребно за прилагођавање ваше компоненте. Истовремено, то олакшава одржавање омогућавањем ажурирања заданих вредности на једном месту.

2 - Основна компонента је превише сложена

Када базна компонента коју користите за креирање одређеније компоненте прихвата превише параметара. Дакле, његово стварање би створило неке проблеме. На пример:

  • Морате да убацујете већину - ако не и све - параметре од нове до основне компоненте. Како све више и више компоненти произилазе из њега, свака ажурирања основне компоненте би одражавала огромну количину промена. Стога доводи до већег броја бугова.
  • Што се више компоненти ствара, то је теже документовати и памтити различите нијансе. Ово се посебно односи на нове програмере.

Када креирати нове компоненте

1 - Проширење функционалности

Могуће је створити нову компоненту када проширите функционалност са једноставније компоненте. Помаже вам да спречите пропуштање логике специфичне за компоненту у другу компоненту. Ово је посебно корисно током примене додатног понашања.

/ * Изјава * /
{{уи-буттон-падајуће ставке = предмети}}
/* Под хаубом */
{{# уи-тастер онЦлицк = (акција 'тогглеДропдовн')}}
  {{лабел}} <и цласс = "фа фа-цхеврон-довн"> 
{{/ уи-тастер}}
{{#иф јеЕкпандед}}
  {{уи-падајуци предмети = предмети}}
{{/ако}}

Горњи пример користи компоненту дугмета. Ово проширује свој изглед тако да подржава фиксну икону, док укључује падајућу компоненту и стање видљивости.

2 - Параметри украшавања

Постоји још један могући разлог за стварање нових компоненти. Ово је када је потребно контролирати доступност параметара или украшавати задане вриједности.

/ * Изјава * /
{{форм-датепицкер онФоцус = (акција 'уради нешто')}}
/* Под хаубом */
{{форм-инпут онФоцус = (акција '_онФоцус')}}
_онФоцус () {
  $ (овај.елемент)
    .финд ('улаз')
    .селецт (); / * Одаберите вредност поља у фокусу * /
  тхис._хандлеЦаллбацк ('онФоцус'); / * Покреће повратни позив * /
}

У овом примеру је компоненти дато функцију која се требала звати када је поље фокусирано.

Унутра, уместо да прође повратни позив директно на базну компоненту, он прелази унутрашњу функцију. Ово обавља одређени задатак (одабир вредности поља), а затим позива предвиђени повратни позив.

Не преусмерава све параметре прихваћене од стране основне улазне компоненте. Ово помаже у контроли опсега одређених функција. Такође се избегавају непотребне потврде.

У мом случају, догађај онБлур замењен је другим догађајем - онЦханге. То се покреће када корисник или испуни поље или одабере датум у календару.

Закључак

Приликом састављања компоненти размислите о својој страни као и о томе ко користи ту компоненту у свом свакодневном животу. На овај начин сви побјеђују.

Најбољи резултат долази од свих у групи који раде оно што је најбоље за себе и групу - Јохн Насх

Такође, не стидите се тражити повратне информације. Увек ћете пронаћи нешто на чему се може радити.

Да бисте још више пооштрили своје инжењерске софтверске вештине, препоручујем да следите серију Ерица Еллиотта „Састављање софтвера“. То је супер!

Па, надам се да сте уживали у чланку. Молимо вас да узмете ове концепте, претворите се у своје идеје и поделите их са нама!

Такође, слободно ми се обратите на твиттеру @гцоломбо_! Волио бих чути ваше мишљење, па чак и радити заједно.

Хвала!