Ich heiĂźe Ksyusha Lugovaya. Bei SberCorus verwalte ich die Korus-UI React-Komponentenbibliothek.
Fast jeder Entwickler steht früher oder später vor dem Problem, eine Bibliothek auszuwählen, und manchmal kann die Lösung nicht trivial sein. Es stellen sich Fragen: Was sollte bei der Auswahl einer Bibliothek beachtet werden, welche beliebten Lösungen bietet der Markt, welche Vor- und Nachteile haben sie? Bewertungen und Testimonials helfen Ihnen nicht immer, eine Lösung zu finden.
In der Entwicklungswelt gibt es keine perfekte Lösung für alle Situationen. In diesem Artikel werde ich Ihnen daher erläutern, wie wir dieses Problem lösen, und anhand von Beispielen für die Analyse mehrerer gängiger Lösungen analysieren, wie Sie eine Bibliothek mit React-Komponenten für Ihr Projekt auswählen können.
Die Hauptkriterien fĂĽr die Auswahl einer Bibliothek
Bibliotheksnutzungsszenarien. Das klingt offensichtlich, aber ein klares Verständnis der Aufgaben ist das primäre Auswahlkriterium.
Anwendungskomponententypen. Die Art der Anwendung bestimmt, welche Komponenten Sie benötigen. Oft reicht eine Reihe von Schaltflächen / Kontrollkästchen, grundlegenden Eingabefeldern, Listen / Menüs mit vorgefertigten Stilen aus. Dies bedeutet, dass Sie einfache Komponenten mit einem Minimum an Einstellungen und vorgefertigten Stilen verwenden können.
Anpassung, Formatierung und Interaktivität im Design. Wenn Sie Ihre Komponenten erheblich formatieren und formatieren müssen, ist es auch wichtig, dies im Voraus zu entscheiden.
Wenn die Anforderungen klar angegeben sind, beantworten Sie die Fragen:
Ist die Projektdokumentation gut geschrieben, gibt es interaktive Beispiele?
Wie aktiv wird das Projekt unterstĂĽtzt?
Wie viele Probleme sind im Projekt und wie schnell werden sie gelöst?
Ist das Projekt kostenlos oder kommerziell lizenziert?
Wie einfach lassen sich die Komponenten anpassen?
Wird der Bibliothekscode durch Tests abgedeckt?
?
, . , — .
, :
Material-UI,
Semantic-UI-React,
yandex-ui,
arui-feather,
Korus-UI.
, – Material-UI Semantic-UI-React, .
– , (, ) , opensource .
.
— , .
.
Layout-
, , , . :
;
props.children;
;
: h1, section, div, span, Icon, Avatar.
- , . , Material-UI Semantic-UI . - .
- (controls)
, , , , — , «» .
:
;
props;
UI (disabled, required, isLoading).
, .
:
;
layout- (, , );
.
|
|
Layout |
Controls |
Modules |
|
Material-UI |
App Bar, Avatars, Badges, Bottom Navigation, Divider, Grid List, Lists, Paper, Progress, Snackbar, Tables, |
Button, Chip, Selection Controls, Text Fields, Pickers* |
Dialog, Cards, Drawers, ExpansionPanel, Menu, Stepper, Tabs, Tooltip |
26** |
Semantic-UI-React |
Container, Divider, Flag, Header, Icon, Image, Label, List, Loader, Placeholder, Rail, Reveal, Segment, Step, Breadcrumb, Form, Grid, Menu, Message, Table, Advertisement, Card, Comment, Feed, Item, Statistic |
Button, Input, Checkbox, Radio, Select, Text Area |
Accordion, Dimmer, Dropdown, Embed, Modal, Popup, Progress, Rating, Search, Sidebar, Sticky, Tab, Transition, Visibility, Confirm, Pagination, Portal, Ref, Transitionable Portal |
52 |
yandex-ui |
Badge, Divider, Icon, Image, Text, UserPic, ListTile, Spacer, Link, Spin |
Attach, Button, Checkbox, Menu, Radiobox, RadioButton, Select, Slider, Textarea, Textinput, Tumbler |
TabsMenu, Drawer, Dropdown, Messagebox, Modal, Popup, TabsPanes, Tooltip, Progress |
30 |
arui-feather |
Amount, CardImage, FlagIcon, Form, GridRow, GridCol, Heading, Icon, InputGroup, Label, Link, List, Paragraph, Spin |
Attach, Button, CardInput, CheckBoxGroup, CheckBox, FormField, IconButton, Input, RadioGroup, Radio, Select, TagButton, Textarea, Toggle |
CalendatInput, Calendar, Collapse, EmailInput, InputAutocomplete, IntlPhoneInput, Menu, MoneyInput, Notification, PhoneInput, Plate, Popup, ProgressBar, Sidebar, SlideDown, Tabs |
44 |
Korus-UI |
HTML tags factory***, Currency, Tags |
Button, Checkbox, Input, Radio, Rating, Slider, Switcher, Textarea |
Autocomplete, ButtonGroup, Collapse, Collapsible, DatePicker, DateRange, DateTimePicker, DateTimeRange, Dropdown, DropdownLink, DropdownSelect, Dropzone, FileDrop, FileUpload, Loader, MaskedInput, Modal, MultiSelect, Notifications, NumericRange, NumericTextBox, Pagination, Password, ProgressBar, StatusBar, StickyPanel, Tabs, TimePicker, TimeRange, Tooltip, Tour, Validation, VStepper, Wizard, form |
45 + - HTML- |
*Material-UI
** ,
***Korus-UI HTML- c API
50% Material-UI Semantic-UI-React 30% yandex-ui arui-feather — layout-. Korus-UI 70% — .
. .
Material-UI
MuiThemeProvider. React .
. className.
classes.
CSS-in-Js, , CSS-. CSS-in-Js HOC withStyles() makeStyles() .
Semantic-UI-React
Semantic-UI-React , Semantic-UI.
, .
:
-
css- ;
-
-
yandex-ui
. .
:
-
() ;
- yaml json. (css, json, js, ios, android) .
arui-feather ( )
. className, .
Korus-UI ()
LedaProvider. React .
. API- (. theme). .
. , , ( Loader ).
.
Material-UI
, List <ul>
. React :
<List component="nav">
<ListItem button>
<ListItemText primary="Trash" />
</ListItem>
<ListItem button>
<ListItemText primary="Spam" />
</ListItem>
</List>
Semantic-UI
Semantic-UI-React as:
<Button as='a' />
React- . .
yandex-ui
:
import React from 'react'
import { useRenderOverride } from '@yandex/ui/lib/render-override'
const ElementOriginal = ({ children }) => <div>{children}</div>
const MyComponent = ({ renderElement }) => {
const Element = useRenderOverride(ElementOriginal, renderElement)
return (
<>
<Element />
</>
)
}
yandex-ui .
arui-feather ( )
.
Korus-UI
API. Render. , , .
:
labelRender={() => <MyCustomLabel />}
:
({ Element, elementProps, componentProps, componentState }) => React.Node
Element
-
elementProps
- props
componentState
,componentProps
- props state
, , :
<L.CheckBox
labelRender={({ elementProps }) => <MyCustomLabel {…elementProps} />}
>
Label
</L.CheckBox>
React- 2 :
Typescript
PropTypes
React Typescript. , . PropTypes — .
Typescript. Semantic-UI JS, Typescript Semantic-UI-React, React.
— . , . , . .
, — . .
( ) ( ).
.
|
|
|
|
% |
Material-UI |
Chai, Mocha, Sinon |
Unit |
95.28% Statements 87.22% Branches 97.51% Functions 95.26% Lines |
Semantic-UI |
Jasmine, Karma |
Unit |
|
Semantic-UI-React |
Chai, Enzyme |
Unit |
|
yandex-ui |
Jest, Enzyme |
Unit |
|
arui-feather |
Jest, Enzyme |
Unit |
88.1% Statements 73.84% Branches 66.61% Functions 87.19% Lines |
Korus-UI |
Cypress, Jest |
Unit, end-to-end |
69.28% Statements 56.14% Branches 66.29% Functions 71.78% Lines |
, . Storybook .
|
|
|
|
Storybook |
Material-UI |
https://material-ui.com/ru/ |
- |
- |
Semantic-UI-React |
https://react.semantic-ui.com/ |
+ |
- |
yandex-ui |
https://yastatic.net/s3/frontend/lego/storybook/index.html |
- |
+ |
arui-feather |
https://digital.alfabank.ru/ |
+ |
- |
Korus-UI |
https://opensource.esphere.ru/korus-ui/ |
+ |
+ |
, . , .
. , , , , . : , .
-. , . , , .
Pulse GitHub Pull Request . Insights . .
Material-UI
Semantic-UI
yandex-ui
arui-feather ( )
Korus-UI ()
GitHub npm-. , . .
, — SEO-, . , , Stackoverflow, Medium, DEV. issues .
, , . .
|
|
|
|
, % |
Material-UI |
63 400 |
6 372 353 |
0,99 |
Semantic-UI |
48 800 |
541 299 |
9 |
Semantic-UI-React |
11 900 |
8 620 967 |
0,14 |
@yandex/ui |
212 |
15 902 |
1,33 |
arui-feather ( ) |
559 |
26 744 |
2 |
. . , , , . , .
: . , .
, , ( ). (-), .
.
: . , , , «».
Korus-UI
const BasicForm = () => (
<L.Div>
<L.Input
isRequired
requiredMessage="Login is required"
form="form"
name="login"
placeholder="Login"
/>
<L.Input
isRequired
requiredMessage="Password is required"
form="form"
name="password"
placeholder="Password"
/>
<L.Button _warning form="form">
Submit
</L.Button>
</L.Div>
);
Material-UI
const BasicForm = () => {
const [login, setLogin] = React.useState("");
const [loginError, setLoginError] = React.useState(false);
const [password, setPassword] = React.useState("");
const [passwordError, setPasswordError] = React.useState(false);
return (
<div>
<form
onSubmit={(e) => {
e.preventDefault();
setLoginError(!login);
setPasswordError(!password);
}}
>
<p>
<TextField
error={loginError}
placeholder="Login"
value={login}
onChange={(e) => {
setLoginError(false);
setLogin(e.target.value);
}}
onBlur={(e) => {
setLoginError(!login);
}}
helperText={loginError && "Login is required"}
/>
</p>
<p>
<TextField
error={passwordError}
placeholder="Password"
value={password}
onChange={(e) => {
setPasswordError(false);
setPassword(e.target.value);
}}
onBlur={(e) => {
setPasswordError(!password);
}}
helperText={passwordError && "Password is required"}
/>
</p>
<Button type="submit" color="primary" variant="contained">
Sign Up
</Button>
</form>
</div>
);
};
Semantic-UI-React
const BasicForm = () => {
const [login, setLogin] = React.useState("");
const [loginError, setLoginError] = React.useState(false);
const [password, setPassword] = React.useState("");
const [passwordError, setPasswordError] = React.useState(false);
return (
<div>
<Form
onSubmit={(e) => {
e.preventDefault();
setLoginError(!login);
setPasswordError(!password);
}}
>
<Form.Group>
<Form.Input
error={loginError && { content: "Login is required" }}
placeholder="Login"
name="login"
value={login}
onChange={(e) => {
setLoginError(false);
setLogin(e.target.value);
}}
onBlur={(e) => {
setLoginError(!login);
}}
/>
<Form.Input
error={passwordError && { content: "Password is required" }}
placeholder="password"
name="password"
value={password}
onChange={(e) => {
setPasswordError(false);
setPassword(e.target.value);
}}
onBlur={(e) => {
setPasswordError(!password);
}}
/>
<Form.Button content="Submit" />
</Form.Group>
</Form>
</div>
);
};
arui-feather
const BasicForm = () => {
const [login, setLogin] = React.useState("");
const [loginError, setLoginError] = React.useState(false);
const [password, setPassword] = React.useState("");
const [passwordError, setPasswordError] = React.useState(false);
return (
<Form
onSubmit={(e) => {
e.preventDefault();
setLoginError(!login);
setPasswordError(!password);
}}
>
<FormField>
<Input
error={loginError && "Login is required"}
placeholder="Login"
value={login}
onChange={(value) => {
setLoginError(false);
setLogin(value);
}}
onBlur={(e) => {
setLoginError(!login);
}}
/>
</FormField>
<FormField>
<Input
error={passwordError && "Password is required"}
placeholder="Password"
value={password}
onChange={(value) => {
setPasswordError(false);
setPassword(value);
}}
onBlur={(e) => {
setPasswordError(!password);
}}
/>
</FormField>
<FormField>
<Button view="extra" type="submit">
Submit
</Button>
</FormField>
</Form>
);
};
yandex-ui
const BasicForm = () => {
const [login, setLogin] = React.useState("");
const [loginError, setLoginError] = React.useState(false);
const [password, setPassword] = React.useState("");
const [passwordError, setPasswordError] = React.useState(false);
return (
<form
onSubmit={(e) => {
e.preventDefault();
setLoginError(!login);
setPasswordError(!password);
}}
className={cnTheme(theme)}
>
<Textinput
error={loginError}
placeholder="Login"
value={login}
onChange={(e) => {
setLoginError(false);
setLogin(e.target.value);
}}
onBlur={(e) => {
setLoginError(!login);
}}
hint={loginError && "Login is required"}
/>
<Textinput
error={loginError}
placeholder="Password"
value={password}
onChange={(e) => {
setPasswordError(false);
setPassword(e.target.value);
}}
onBlur={(e) => {
setPasswordError(!login);
}}
hint={passwordError && "Password is required"}
/>
<Button type="submit" view="action">
Submit
</Button>
</form>
);
};
, Korus-UI , .
Material-UI yandex-ui , Semantic-UI-React arui-feather <form>
.
, Korus-UI. .
React-
React-.
|
|
Korus-UI () |
Material-UI |
Semantic-UI-React |
arui-feather ( ) |
yandex-ui |
|
|
Storybook |
+ |
– |
– |
– |
+ |
|
+ |
– |
+ |
+ |
– |
|
|
Pull Request |
70 |
241 |
2 |
0 |
0 |
|
|
|
|
|
|
|
|
> 50% |
+ |
+ |
– |
+ |
|
E2E |
+ |
– |
– |
– |
– |
|
|
Chrome |
85.0.4183.121 |
>= 49 |
Last 2 v. |
Last 2 v. |
Last 2 v. |
Firefox |
81.0.1 |
>= 52 |
Last 2 v. |
Last 2 v. |
>= 23 |
|
Edge |
85.0.564.44 |
>=14 |
12+ |
Last 2 v. |
|
|
IE |
11 |
11 |
11+ |
11+ |
11+ |
|
Safari |
14 |
>= 10 |
Last 2 v. |
Last 2 v. |
|
|
Opera |
|
|
|
Last 2 v. |
>= 12.1 |
|
Yandex |
|
|
|
Last 2 v. |
? |
|
Android |
|
|
4.4+ |
5+ |
>= 4 |
|
iOS Safari |
|
|
7+ |
Last 2 v. |
>= 5.1 |
|
|
|
+ |
+ |
+ |
– |
+ |
|
|
+ |
+ |
+ |
– |
– |
|
|
Typescript |
Typescript |
Typescript |
Typescript |
Typescript |
|
GitHub , % |
– |
0,99 |
0,14 |
2 |
1,33 |
|
|
+ |
– |
+ |
+ |
– |
|
+ |
– |
– |
– |
– |
|
. , .
, , .
Korus-UI
: ? React .
, , . — , .
: , . .
React-, . , . , , .
Korus-UI 1,5 . opensource-.
Korus-UI
Korus-UI : form, . , , . , L.form()
. , .
Korus-UI onValidationFail, , . — .
Korus-UI — . :
RegExp
( )
isValid
unmounted
,
API
, _. css-:
<L.Div _flexBox> -> <div class="flex-box"></div>
className .
theme, css- .
Render (. ).
, :
{
…Event, // , React'
// component,
component: {
isValid?: boolean, // , onBlur
name?: string, // ,
value: any, //
… // (. API )
}
}
:
is: isOpen
, isValid
, isRequired
, isDisabled
has: hasCloseButton
should: shouldCorrectValue
ref
.
Korus-UI ref, React.
Korus-UI
, . , issue .
iOS Android. . .
React- Material-UI, Semantic-UI-React, arui-feather ( ), yandex-ui, Korus-UI (), .
, :
Korus-UI, . , , Korus-UI .
. , Storybook.
Korus-UI opensource GitHub. opensource, , :)
Ich möchte auch dem Entwicklungsteam von SberCorus, dem Vater und ideologischen Inspirator der Bibliothek, Artem Povolskikh, meinen Dank aussprechen . Wenn Sie daran interessiert sind, wie die Front-End-Entwicklung in SberCorus funktioniert, lesen Sie den Artikel von Artyom .
Teilen Sie Ihre Erfahrungen mit Komponentenbibliotheken in den Kommentaren. Es ist interessant zu diskutieren, auf welche Vor- und Nachteile Sie aus persönlicher Erfahrung gestoßen sind und welche Funktionen Ihnen dabei fehlen.