Встречайте Material-UI – вашу новую любимую библиотеку пользовательского интерфейса

1656628825 vstrechajte material ui – vashu novuyu lyubimuyu biblioteku polzovatelskogo interfejsa

от Code Realm

1*FDNeKIUeUnf0XdqHmi7nsw

Обновление (17.05.2018): Вышел Material-UI версии 1.0.0! Просмотрите эту публикацию Оливье.

га? Еще одна библиотека? Что не так из Bootstrap? А почему бы не v0.20?

Прекрасные вопросы! Начнём с короткого вступления. В двух словах, Material-UI – это проект с открытым кодом, содержащий компоненты React, реализуемые Material Design от Google.

Он стартовал в 2014 году, вскоре после того, как React вышел на публику и с тех пор возросла популярность. Имея более 35 000 звезд на GitHub, Material-UI является одной из лучших библиотек пользовательского интерфейса для React.

Однако его успех не обошелся без проблем. Разработанный с помощью LESS, Material-UI v0.x был подвержен распространенным ошибкам CSS, таким как глобальный масштаб, ведущий проект на траектории CSS-in-JS. Во как next возник в 2016 году.

Путь к лучшему стилю, по словам Оливье Тассинари, начался со встроенных стилей, но их неоптимальная производительность и ограниченная поддержка функций (например, псевдоселекторы или медиазапросы) в конце концов привели команду к переходу на JSS. И они сделали разумный выбор.

Каков ажиотаж с выпуском v1?

Это плохо. Он не только решает проблемы, присущие LESS, но также открывает массу отличных функций, в частности

  • динамические стили, созданные во время выполнения
  • вложенные темы с интуитивно понятными заменами
  • сокращенное время загрузки с разделением кода

И многое другое. Библиотека также достаточно зрела, чтобы ее можно было использовать в производстве, настолько, что команда предлагает v1 для всех новых проектов.

Хорошо, мы собираемся создать приложение?

Рада, что вы спросили! Для этой демонстрации мы создадим простую фитнес-программу. Уже всем надоели программы для дел, не правда ли?

Читать это здорово, но смотреть часто веселее! Просмотрите этот список воспроизведения, созданный на YouTube, если вы хотите создать более расширенное приложение.

Ладно, вы меня убедили. Как начать?

Сначала мы загрузим наше приложение с помощью create-react-app

create-react-app mui-fitnesscd mui-fitnesscode .

А как насчет Material-UI?

Если у вас есть пряжа, установка проста

yarn add @material-ui/core

Иначе из npm

npm i @material-ui/core

Не так давно мы бы уточнили@next тег, чтобы получить последнюю предыдущую версию (например, это могло выглядеть так: v1.0.0-beta.47). Теперь, когда и v1, и v0.x запущены material-ui нам нужно ссылаться на ядро ​​библиотеки /core для таргетинга на последнюю версию. Не пропустите последнюю часть, иначе вы попадете в конюшню0.20 зависимость!

Подождите, это правда?

Почти! И последнее – это шрифты. Мы будем использовать рекомендованный шрифт Roboto от CDN от Google:

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">

Кроме того, вы можете скачать его с NPM с помощью

yarn add typeface-roboto# or npm i typeface-roboto

в этом случае вам понадобится импорт в корне вашего проекта

// Make sure you only load 300, 400, & 500 font weights though!import 'typeface-roboto'

Готово! Что делать дальше?

Ну, давайте переделаем нашу App.js компонент, прежде чем мы пойдем дальше

import React, { Component } from 'react'
export default class App extends Component {  state = {    exercises: [],    title: ''  }
  render() {    return <h1>Exercises</h1>  }}

А почему бы и не убрать index.js пока мы на этом?

import React from 'react'import { render } from 'react-dom'import App from './App'
render(<App />, document.getElementById('root'))

Не стесняйтесь удалить оставшиеся файлы под srcпоскольку они нам не понадобятся.

Откуда входит Material-UI?

Достаточно справедливо, пора увидеть это в действии. Давайте изменим безобразное h1 к прекрасному Typography заголовок:

import Typography from '@material-ui/core/Typography'
...
  render() {    return (      <Typography variant="display1" align='center' gutterBottom>        Exercises      </Typography>    )  }}

Обратите внимание, что с версии 1.0.0-rc.0 MUI перешел к @material-ui/core и путь импорта был выровнен. Это было последнее кардинальное изменение в предыдущем выпуске.

Тогда вперед и беги yarn start увидеть магию.

1*3LXrxIWyUdUQUqTyqfd_9w
Заголовок размером «Показать 1» с нижним полем по центру по горизонтали

Мы в хорошем начале! Typography компонент поставляется с предварительно определенным набором типоразмеров. Другой variants включают body1, title, display2, и так дальше. Среди других встроенных реквизитов есть align который мы используем здесь для центрирования текста по горизонтали, и gutterBottom что добавляет нижнее поле.

Почему бы нам не расширить это до формы, чтобы мы могли создавать свои упражнения? Мы начнем с а TextField и привязать его к title на государство

import Typography from '@material-ui/core/Typography'import TextField from '@material-ui/core/TextField'
...
  handleChange = ({ target: { name, value } }) =>    this.setState({      [name]: value    })
  render() {    const { title } = this.state    return (      ...      <form>        <TextField          name="title"          label="Exercise"          value={title}          onChange={this.handleChange}          margin='normal'        />      </form>    )  }}

Конечно, нам нужно сделать React счастливым, оборачивая Typography и form с родительским элементом Что может быть лучшей возможностью для фона, похожего на листовку из бумаги? Обратимся к Paper потом

import Paper from '@material-ui/core/Paper'
...
  render() {      const { title } = this.state      return <Paper>        ...      </Paper>    }  }}

Пора начать использование импорта с именами (если наша настройка Webpack позволяет раскачать дерево):

import { Paper, Typography, TextField } from '@material-ui/core'

Сладкий! А какая польза в форме без кнопки «Отправить»? Buttons является основным компонентом Material-UI; вы увидите их везде. Например,

import {  Paper,  Typography,  TextField,  Button } from '@material-ui/core'...        <Button          type="submit"          color="primary"          variant="raised"        >          Create        </Button>      </form>    </Paper>  }}

Это должно хорошо читаться. type является обычным реквизитом React, color и variant зависят от материала пользовательского интерфейса и образуют кнопку в форме прямоугольника. Другой вариант был бы fab для плавающей кнопки, например.

1*GWviICnReMU62qHX2V1iKA
Не самая красивая форма в мире, но через мгновение мы сделаем ее лучше!

Но это не делает многое. Нам придется перехватить событие отправки формы

    return <Paper>      ...      <form onSubmit={this.handleCreate}>        ...      </form>    </Paper>  }}

а затем обработайте это с помощью

  handleCreate = e => {    e.preventDefault()
    if (this.state.title) {      this.setState(({ exercises, title }) => ({        exercises: [          ...exercises,          {            title,            id: Date.now()          }        ],        title: ''      }))    }  }

Вау! Что это за загадочный код? Очень быстро мы

  1. Запретить перезагрузку страницы по умолчанию
  2. Убедитесь, что title поле не пустое
  3. Установите состояние с помощью функции обновления, чтобы смягчить асинхронные обновления.
  4. Деструктурирование exercises и title от prevState объект
  5. Разложите exercises на следующее состояние с новым объектом упражнения
  6. Сбросьте настройки title чтобы очистить поле ввода

Кажется, я должен был сказать, что я тоже влюблен в ES6. Разве мы не все?

Но как их перечислить?

Сейчас подходящее время. Есть ли компонент списка? Конечно, глупый гусь!

Внутри а Listмы просмотрим наши exercises и вернуть а ListItem с некоторыми ListItemText для каждого

import { List, ListItem, ListItemText } from '@material-ui/core'
...
  render() {    const { title, exercises } = this.state    return <Paper>          ...      <List>        {exercises.map(({ id, title }) =>          <ListItem key={id}>            <ListItemText primary={title} />          </ListItem>        )}      </List>    </Paper>  }}

Давайте также жестко запрограммируем несколько начальных упражнений, чтобы получить что-нибудь на экране. Вы уже догадались, троица всех тренировок по тяжелой атлетике, женщины и господа:

  state = {    exercises: [      { id: 1, title: 'Bench Press' },      { id: 2, title: 'Deadlift' },      { id: 3, title: 'Squats' }    ],    title: ''  }
1*7v9-VMXQ-7grca3AxVBtUw
Теперь мы можем создавать и перечислять наши упражнения!

И последнее, но не менее важное, наши пользователи, вероятно, допускают ошибки, поэтому мы лучше добавляем кнопку удаления у каждого упражнения, чтобы они могли удалять записи, которые они больше не хотят из своего списка.

Мы можем использовать ListItemSecondaryAction сделать именно это. Расположенный в крайнем правом углу элемента списка, он может содержать вторичный элемент управления, например IconButton с определенным действием

import {  /*...*/,  ListItemSecondaryAction,  IconButton} from '@material-ui/core'
...
          <ListItem key={id}>            <ListItemText primary={title} />            <ListItemSecondaryAction>              <IconButton                color="primary"                onClick={() => this.handleDelete(id)}              >                {/* ??? */}              </IconButton>            </ListItemSecondaryAction>          </ListItem>
...

И давайте не забываем об обработчике удаления:

  handleDelete = id =>    this.setState(({ exercises }) => ({      exercises: exercises.filter(ex => ex.id !== id)    }))

который просто отфильтрует наши упражнения к не отвечающим id из той, которую нужно удалить.

Можем ли мы иметь значок мусора внутри кнопки?

Да, это было бы здорово! Хотя вы можете использовать значки материалов из CDN от Google непосредственно с любым Icon или SvgIcon компонентов, часто лучше использовать готовые пресеты.

К счастью, для них есть пакет Material-UI

yarn add @material-ui/icons# or npm i @material-ui/icons

Он экспортирует более 900 официальных значков материалов как компоненты React, а названия иконок почти идентичны, как вы увидите ниже.

Скажем, мы хотели добавить корзину значок. Сначала мы перейдем к material.io/icons, чтобы узнать его точное название

1*nGrpog4i4mCEWNXIeGeQiA
Google предлагает два варианта значка корзины: «удалить» и «удалить навсегда»

Затем мы превращаем это имя в PascalCase в нашем пути импорта

import Delete from '@material-ui/icons/Delete'

Как и с компонентами Material-UI, если в вашей установке включено встряхивание дерева, вы можете сократить импорт в

import { Delete } from '@material-ui/icons'

что особенно полезно при импортировании нескольких пиктограмм одновременно.

Теперь, когда у нас есть значок корзины, давайте отразим его внутри кнопки удаления

<IconButton color="primary" onClick={() => this.handleDelete(id)}>  <Delete /></IconButton>
1*0s5edmQdwwrVQ7qEVN9i-A
И с этим наше приложение CRUD MVP можно считать исполненным!

Как сделать так, чтобы форма выглядела менее безобразной?

Ах, стиль. Я думал, ты никогда не спросишь! Нежное прикосновение CSS не повредит. Итак, импортируем ли внешнюю таблицу стилей с глобальными стилями? Или возможно использовать модули CSS и назначать нашим элементам имена классов с областью действия? Не совсем.

Под капотом Material-UI расширяет библиотеку CSS-in-JS, известную как react-jss.

Это интеграция React библиотеки JSS того же автора Олега Исонена. Помните, мы затрагивали это сначала? Его основная идея – позволить вам определять стили в JavaScript. Тем не менее, что выделяет JSS среди других библиотек, это поддержка SSR, небольшой размер пакета и богатая поддержка плагинов.

Давайте попробуем! В нашем App компонента, создайте объект стилей так же, как и со встроенными стилями. Тогда придумайте, к примеру, ключ rootссылаясь на корень Paper элемент и выпишите некоторые стили в camelCase

const styles = {  root: {    margin: 20,    padding: 20,    maxWidth: 400  }}

Далее импортируем withStyles HOC от material-ui

import { withStyles } from '@material-ui/core/styles'

и завернуть App компонент с ним, мимоходом styles объект как arg

export default withStyles(styles)(  class App extends Component {    ...  })

Обратите внимание, что вы также можете использовать withStyles HOC в качестве декоратора. Имейте в виду, что create-react-react пока не поддерживает декоратор из коробки, поэтому если вы настаиваете на их использовании, вам нужно будет удалить или развить, чтобы настроить конфигурацию.

Это введет a classes подпирать в App содержит динамически сгенерированное название класса для нашего root элемент

1*GDot9qSrDic2OH-k6EEKXw
console.log(this.props) раскрывает объект классов

Имя класса гарантированно будет уникальным, и его часто сокращают в производственном сборнике. Затем мы назначаем его Paper через className атрибут

    render() {      const { title, exercises } = this.state      const { classes } = this.props
      return <Paper className={classes.root}>        ...      </Paper>    }
1*gbPzl0I7P961-YwiyoS92g
Бумажный компонент с применением базового стиля

Как действует эта магия? Оказывается, withStyles несет ответственность за грязную работу. За кулисами он ввел в DOM ряд стилей <style> теги. Вы можете заметить их, если покопатьсяo the с инструментами разработчика

1*3shG1_HG51pbygI2-g0bSA
Ага! Вот наши стили для компонента App.

Вы также могли увидеть другие style теги, связанные с родными компонентами, например MuiListItem для ListItem компонент, который мы импортировали раньше. Они автоматически вводятся по требованию для каждого импортируемого элемента интерфейса.

Это означает, что Material-UI никогда не будет загружать стили для компонентов, которые мы не используем. Таким образом, повышается производительность и ускоряется время загрузки. Это очень отличается от Bootstrap, который требует загрузки всего монолитного пакета CSS, независимо от того, используете ли вы его огромный ассортимент классов или нет.

Давайте также оформим форму, чтобы она выглядела аккуратно

const styles = {  root: {    ...  },  form: {    display: 'flex',    alignItems: 'baseline',    justifyContent: 'space-evenly'  }}

Это делает текстовое поле и кнопку хорошо разнесенными. Если вам понадобятся дополнительные разъяснения по поводу макета Flexbox, не стесняйтесь обращаться к align-items и justify-content на CSS-Tricks.

1*FMK3C9iGnWttA0mtwUQpYg
Надеемся, это утолит наш голод к эстетике.

Конечно, что тогда с тематикой?

withStyles HOC предназначен для настройки одноразового компонента, но не подходит для перезаписи всей программы. Каждый раз, когда вам нужно применить глобальные изменения ко всем компонентам Material-UI, первым желанием будет обратиться к theme объект.

Темы предназначены для управления цветами, интервалами, тенями и другими атрибутами стиля элементов интерфейса. Material-UI поставляется со встроенным свет и темный типы тем, свет по умолчанию.

Если мы перевернем нашу styles в анонимную функцию, она получит theme объект как аргумент, чтобы мы могли его проверить

const styles = theme => console.log(theme) || ({  root: ...,  form: ...})
1*qtc-xSN8m0QC-jLQfNz3sA
Объект темы по умолчанию с переменными конфигурациями, как показано на консоли

Вы можете настроить свою тему с помощью переменных конфигураций, например palette, type, typographyтому подобное. Чтобы ознакомиться со всеми вложенными свойствами и параметрами, посетите раздел Тема по умолчанию в документации Material-UI.

Скажем, мы хотели изменить основной цвет blue к orange. Для начала нам нужно создать тему из createMuiTheme помощник в index.js

import { createMuiTheme } from '@material-ui/core/styles'
const theme = createMuiTheme({ /* config */ })

В Material-UI цвета определяются под palette собственность theme. Цветовая палитра подразделяется на намерения, включающие primary, secondaryи error. Чтобы настроить намерение, вы можете просто указать цветной объект

import { orange } from '@material-ui/core/colors'
const theme = createMuiTheme({  palette: {    primary: orange  }})

После нанесения будет рассчитан цвет light, main, darkи contrastText вариации. Однако для более детального управления можно передать обычный объект с помощью любого из этих четырех клавиш

const theme = createMuiTheme({  palette: {    primary: {      light: orange[200] // same as '#FFCC80',      main: '#FB8C00', // same as orange[600]      dark: '#EF6C00',      contrastText: 'rgb(0,0,0)'    }  }})

Как видите, отдельные цвета могут быть выражены как шестнадцатеричной, так и rgba строкой (#FFCC80) и пару оттенков/оттенков (orange[200]).

1*SLj1X7h5Jx-PuLtS2sbsjw
Основное намерение с голубыми цветами по умолчанию (слева) и объектом оранжевого цвета (справа)

Создать тему самостоятельно будет недостаточно. Чтобы перезаписать тему по умолчанию, нам нужно разместить MuiThemeProvider в корне нашего приложения и передайте нашу настройку theme как реквизит

import { /*...*/, MuiThemeProvider } from '@material-ui/core/styles'
const theme = createMuiTheme({  palette: {    primary: orange  }})
render(  <MuiThemeProvider theme={theme}>    <App />  </MuiThemeProvider>,  document.getElementById('root'))

MuiThemeProvider потом передаст theme ко всем его дочерним элементам через контекст React.

1*6TiadjlFJlCFIZnmXP0yLA
Элементы пользовательского интерфейса, которые наследуют основной цвет, теперь отображаются оранжевым цветом.

Хотя может показаться, что изменить цвет требуется много работы, помните, что эта перезапись распространится на все компоненты, вложенные под провайдером. Кроме цветов, мы можем точно настроить размеры окна просмотра, интервал, непрозрачность и многие другие параметры.

Использование переменных конфигураций во время стилизации ваших компонентов поможет обеспечить согласованность и симметрию в интерфейсе вашего приложения. Например, вместо жесткого кодирования магических значений для margin и padding на нашем Paper компонента, мы могли бы вместо этого полагаться на единицу интервалов вне темы

const styles = ({ spacing: { unit } }) => ({  root: {    margin: unit,    padding: unit * 3,    maxWidth: 400  },  form: ...}

theme.spacing.unit приходит на 8px по умолчанию, но если он используется равномерно в приложении, когда нам нужно обновить его значение, а не очищать всю кодовую базу, нам нужно изменить его только в одном месте, то есть в нашем объекте параметров, которому мы передаем createMuiTheme.

Переменных тем много, и если вы столкнетесь со случаем использования, который не охватывается встроенным объектом темы, вы всегда можете определить собственные собственные переменные. Вот несколько измененная версия нашего фитнес-приложения, демонстрирующая цветовую палитру, тип темы и параметры единиц интервалов

1*KLpF7ayyOr3PCO7vpsAZFg
Переключение между цветами, типами и единицами интервалов на лету

Обратите внимание, что приведенный выше пример является лишь демонстрационным. Он повторно создает новую тему всякий раз, когда меняется параметр, что приводит к тому, что новый объект CSS повторно вычисляется и повторно внедряется в DOM. Чаще конфигурация вашей темы остается статической.

Есть гораздо более интересные функции, которые мы не рассмотрели. Например, Material-UI поставляется с опцией CssBaseline компонент, применяющий межбраузерные нормализации, такие как сброс полей или семейства шрифтов (очень похож на normalize.css).

Что касается компонентов, то у нас есть свой стандарт Grid с макетом из 12 столбцов и пятью окнами просмотра (xs, sm, md, lgи xl). У нас также есть знакомые компоненты, как Dialog, Menuи Tabsа также элементы, такие как Chip и Tooltip. Действительно, есть ряд других, и, к счастью, все они очень хорошо задокументированы с помощью демонстрационного кода с CodeSandbox.

1*EBrJaL41TOHB_9faNZno8w
Пример страницы документации для компонента AppBar https://material-ui-next.com

Кроме того, Material-UI Next также работает с SSR, если вам это нравится. Кроме того, несмотря на то, что он поставляется с JSS из коробки, его можно сделать для работы почти с любой другой библиотекой, например Styled Components, или даже с необработанным CSS.

Обязательно просмотрите официальные документы для получения дополнительной информации.

Надеюсь, это прочитанное вам было полезно! И если вам это настолько нравится, что вы рады узнать больше о Material-UI или React, то, возможно, посмотрите мой канал YouTube?

Спасибо, что зашли! И большое спасибо команде Call-Em-All и всем спонсорам, которые помогли создать эту замечательную библиотеку ❤️

Здоровья,

Алекс

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *