Одна из замечательных особенностей пользовательских свойств CSS заключается в том, что они могут быть частью значения. Допустим, вы используете несколько фонов для создания дизайна. Каждый фон будет иметь свой цвет, изображение, повтор, положение и т. Д. Он может быть многословным!
У вас есть четыре изображения:
тело { фон положение: топ 10px осталось 10px, верхняя 10px, правая 10px, нижняя 10px, правая 10px, нижняя 10px, левая 10px; повторение фона: без повтора; изображение на заднем плане: URL (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-left.svg), URL (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-right.svg), URL (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-right.svg), URL (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg); }
Вы хотите добавить пятую часть в медиа-запрос:
@media (min-width: 1500px) { тело { / * ПОВТОРИТЬ все существующие фоны, затем добавить пятую. * / } }
Это будет супер многословно! Вам придется повторить каждое из этих четырех изображений снова, а затем добавить пятое. Там много дублирования.
Одна возможность - создать переменную для базового набора, а затем добавить пятую гораздо более аккуратно:
тело { --baseBackgrounds: URL (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-left.svg), URL (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-right.svg), URL (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-right.svg), URL (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg); фон положение: топ 10px осталось 10px, верхняя 10px, правая 10px, нижняя 10px, правая 10px, нижняя 10px, левая 10px; повторение фона: без повтора; background-image: var (- baseBackgrounds); } @media (min-width: 1500px) { тело { изображение на заднем плане: Var (- baseBackgrounds), URL (добавлена пятая-background.svg); } }
Но это действительно зависит от вас. Это может иметь больше смысла и быть более простым в управлении, если вы превратили каждое фоновое изображение в переменную, а затем сложили их по мере необходимости.
тело { --bg1: url (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-left.svg); --bg2: url (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-right.svg); --bg3: url (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-right.svg); --bg4: url (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg); --bg5: url (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg); background-image: var (- bg1), var (- bg2), var (- bg3), var (- bg4); } @media (min-width: 1500px) { тело { background-image: var (- bg1), var (- bg2), var (- bg3), var (- bg4), var (- bg5); } }
Вот основная версия этого, включая запрос на поддержку:
См. Статью «
Несколько групповых записей с настраиваемыми свойствами » Криса Койера ( @chriscoyier )
в CodePen .
Несколько групповых записей с настраиваемыми свойствами » Криса Койера ( @chriscoyier )
в CodePen .
Динамическое изменение только части значения - огромная сила пользовательских свойств CSS!
Также обратите внимание, что для фона лучше всего включить в качестве переменной всю стенографию. Таким образом, гораздо проще собрать все вместе, чем нужно что-то вроде ...
--bg_1_url: url (); --bg_1_size: 100 пикселей; --bg_1_repeat: без повтора; /* так далее. */
Проще поместить все свойства в сокращение и использовать по мере необходимости:
тело { --bg_1: url (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-left.svg) top 10px влево 10px / 86px без повтора; --bg_2: url (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-right.svg) верхняя 10px правая 10px / 86px без повтора; --bg_3: url (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-right.svg) внизу 10px справа 10px / 86px без повтора; --bg_4: url (https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg) нижний 10px, левый 10px / 86px без повтора; фон: var (- bg_1), var (- bg_2), var (- bg_3), var (- bg_4); }
Мы уже рассматривали React Hooks раньше, здесь, на CSS-Tricks. У меня есть статья, которая также знакомит их с тем, как их использовать для создания компонентов с помощью функций. Обе статьи являются хорошим обзором высокого уровня о том, как они работают, но они также открывают много возможностей.
Вот что мы собираемся сделать в этой статье. Мы увидим, как хуки облегчают и ускоряют процесс разработки, создавая приложение для чата.
В частности, мы создаем приложение для чата с использованием приложения Create React . При этом мы будем использовать набор React Hooks для упрощения процесса разработки и удаления большого количества стандартного кода, который не нужен для работы.
Доступно несколько хуков Reacts с открытым исходным кодом, и мы будем использовать их. Эти хуки могут напрямую использоваться для создания функций, которые в противном случае потребовали бы больше кода для создания. Они также обычно следуют общепризнанным стандартам для любой функциональности. По сути, это повышает эффективность написания кода и обеспечивает безопасные функциональные возможности.
Давайте посмотрим на требования
Приложение чата, которое мы собираемся создать, будет иметь следующие функции:
- Получить список прошлых сообщений, отправленных с сервера
- Подключиться к комнате для группового чата
- Получайте обновления, когда люди отключаются от комнаты или подключаются к ней
- Отправлять и получать сообщения
Мы работаем с несколькими допущениями при погружении в:
- Мы рассмотрим сервер, который будем использовать как черный ящик. Не беспокойтесь о том, что он работает идеально, так как мы собираемся общаться с ним с помощью простых сокетов.
- Все стили, содержащиеся в одном файле CSS, могут быть скопированы в каталог src. Все стили, используемые в приложении, связаны в репозитории .
Хорошо, мы хотим, чтобы наша среда разработки была готова начать писать код. Прежде всего, React требует как Node, так и npm. Вы можете установить их здесь .
Давайте раскрутим новый проект из Терминала:
npx create-response-app socket-client CD-сокет-клиент начало вечера
Теперь мы должны иметь возможность перейти к http: // localhost: 3000 в браузере и получить страницу приветствия по умолчанию для проекта.
Отсюда мы собираемся разбить работу на крючки, которые мы используем. Это должно помочь нам понять хуки, поскольку мы используем их на практике.
Использование хука setState
Первый хук, который мы собираемся использовать, это useState . Это позволяет нам поддерживать состояние в нашем компоненте, в отличие от, скажем, необходимости писать и инициализировать класс, используя this.state. Данные, которые остаются постоянными, такие как имя пользователя, хранятся в переменных useState. Это гарантирует, что данные остаются легкодоступными, а для их написания требуется гораздо меньше кода.
Основным преимуществом useState является то, что он автоматически отражается в отображаемом компоненте всякий раз, когда мы обновляем состояние приложения. Если бы мы использовали обычные переменные, они не рассматривались бы как состояние компонента и должны были быть переданы как реквизиты для повторной визуализации компонента. Итак, опять же, мы сокращаем много работы и оптимизируем процессы.
Хук встроен прямо в React, поэтому мы можем импортировать его одной строкой:
импортировать React, {useState} из 'Reaction';
Мы собираемся создать простой компонент, который возвращает «Hello», если пользователь уже вошел в систему, или форму входа в систему, если пользователь вышел из системы. Мы проверяем переменную id для этого.
Отправка наших форм будет обрабатываться функцией, которую мы создаем, называемой handleSubmit. Он проверит, заполнено ли поле «Имя». Если это так, мы установим значения идентификатора и комнаты для этого пользователя. В противном случае мы добавим сообщение, напоминающее пользователю, что поле «Имя» необходимо для продолжения.
// App.js импортировать React, {useState} из 'Reaction'; import './index.css'; экспорт по умолчанию () => { const [room, setRoom] = useState (''); const [id, setId] = useState (''); const handleSubmit = e => { e.preventDefault (); const name = document.querySelector ('# name'). value.trim (); const room_value = document.querySelector ('# room'). value.trim (); if (! name) { уведомление о возврате («Имя не может быть пустым»); } SETID (имя); setRoom (document.querySelector ( '# номер') value.trim ().); }; вернуть идентификатор! == ''? ( <DIV> Hello </ DIV> ): ( <div style = {{textAlign: 'center', поле: '30vh auto', ширина: '70% '}}> <form onSubmit = {event => handleSubmit (event)}> <input id = "name" обязательный заполнитель = "Как вас зовут .." /> <br /> <input id = "room" placeholder = "Какая у вас комната .." /> <br /> <button type = "submit"> Submit </ button> </ Форма> </ DIV> ); };
Вот как мы используем хук useState в нашем приложении чата. Опять же, мы импортируем ловушку из React, создаем значения для идентификатора пользователя и местоположения чата, устанавливаем эти значения, если пользователь вошел в систему, и возвращаем форму входа, если пользователь вышел из системы.
Использование крючка useSocket
Мы собираемся использовать хук с открытым исходным кодом, называемый useSocket, для поддержания соединения с нашим сервером. В отличие от useState, этот хук не встроен в React, поэтому нам нужно добавить его в наш проект, прежде чем импортировать его в приложение.
npm добавить use-socket.io-client
Соединение с сервером поддерживается с помощью версии библиотеки React Hooks socket.io , которая является более простым способом поддержания соединений через веб-сокеты с сервером. Мы используем его для отправки и получения сообщений в режиме реального времени, а также для поддержки событий, таких как подключение к комнате.
Клиентская библиотека socket.io по умолчанию имеет глобальные объявления, т. Е. Переменная сокета, которую мы определяем, может использоваться любым компонентом. Однако нашими данными можно манипулировать откуда угодно, и мы не будем знать, где происходят эти изменения. Хук-сокеты противостоят этому, ограничивая определения хуков на уровне компонентов, что означает, что каждый компонент отвечает за свою собственную передачу данных.
Основное использование для useSocket выглядит следующим образом:
const [socket] = useSocket ('socket-url')
Мы будем использовать несколько API-интерфейсов для сокетов по мере продвижения вперед. Ради справки, все они описаны в документации по socket.io . Но сейчас давайте импортируем хук, так как мы его уже установили.
импортировать useSocket из 'use-socket.io-client';
Далее мы должны инициализировать хук, подключившись к нашему серверу. Затем мы запишем сокет в консоли, чтобы проверить, правильно ли он подключен.
const [id, setId] = useState (''); const [socket] = useSocket ('<https://open-chat-naostsaecf.now.sh>'); Socket.connect (); console.log (розетка);
Откройте консоль браузера, и URL-адрес в этом фрагменте должен быть зарегистрирован.
Использование хука useImmer
В нашем приложении чата будет использоваться хук useImmer для управления состоянием массивов и объектов без изменения исходного состояния. Он сочетает в себе useState и Immer для управления неизменным состоянием. Это будет удобно для управления списками людей, которые находятся в сети, и сообщениями, которые необходимо отображать.
Использование Immer с useState позволяет нам изменять массив или объект, создавая новое состояние из текущего состояния, предотвращая мутации непосредственно в текущем состоянии. Это дает нам больше безопасности, так как оставляет текущее состояние нетронутым, в то же время имея возможность манипулировать состоянием в зависимости от различных условий.
Опять же, мы работаем с хуком, который не встроен в React, поэтому давайте импортируем его в проект:
npm добавить use-immer
Основное использование довольно просто. Первое значение в конструкторе - это текущее состояние, а второе значение - функция, которая обновляет это состояние. Затем ловушка useImmer принимает начальные значения для текущего состояния.
const [data, setData] = useImmer (default_value)
Использование хука setData
Заметьте хук setData в этом последнем примере? Мы используем это для создания черновой копии текущих данных, которые мы можем использовать для безопасного манипулирования данными и использования их в качестве следующего состояния, когда изменения становятся неизменяемыми. Таким образом, наши исходные данные сохраняются до тех пор, пока мы не выполним наши функции и не будем абсолютно уверены, что нужно обновлять текущие данные.
setData (draftState => { draftState.operation (); }); // ...или же setData (draft => newState); // Здесь draftState является копией текущих данныхИспользование хука useEffect
Хорошо, мы вернулись к крючку, встроенному прямо в React. Мы будем использовать ловушку useEffect для запуска фрагмента кода только при загрузке приложения. Это гарантирует, что наш код запускается только один раз, а не каждый раз, когда компонент повторно выполняет рендеринг с новыми данными, что хорошо для производительности.
Все, что нам нужно сделать, чтобы начать использовать хук, это импортировать его - установка не требуется!
импортировать React, {useState, useEffect} из'act ';
Нам понадобится компонент, который отображает сообщение или обновление на основе наличия или отсутствия идентификатора отправителя в массиве. Будучи творческими людьми, мы будем называть этот компонент сообщениями.
const Messages = props => props.data.map (m => m [0]! == ''? (<li key = {m [0]}> <strong> {m [0]} </ strong>: <div className = "innermsg"> {m [1]} </ div> </ li>) : (<li key = {m [1]} className = "update"> {m [1]} </ li>));
Давайте поместим нашу логику сокетов в useEffect, чтобы мы не дублировали один и тот же набор сообщений повторно при повторном рендеринге компонента. Мы определим нашу перехватчик сообщений в компоненте, подключимся к сокету, затем настроим прослушиватели для новых сообщений и обновлений в самом перехватчике useEffect. Мы также настроим функции обновления внутри слушателей.
const [socket] = useSocket ('<https://open-chat-naostsaecf.now.sh>'); Socket.connect (); const [messages, setMessages] = useImmer ([]); useEffect (() => { socket.on ('update', message => setMessages (draft => { draft.push (['', message]); })); socket.on ('очередь сообщений', (ник, сообщение) => { setMessages (draft => { draft.push ([ник, сообщение]) }) }); }, 0);
Еще одно прикосновение, которое мы добавим в качестве примера, - это сообщение «join», если имя пользователя и имя комнаты указаны правильно. Это вызывает остальных слушателей событий, и мы можем получать прошлые сообщения, отправленные в эту комнату, вместе с любыми необходимыми обновлениями.
// ... setRoom (document.querySelector ( '# номер') value.trim ().); socket.emit ('join', name, room); }; вернуть идентификатор? ( <section style = {{display: 'flex', flexDirection: 'row'}}> <ul id = "messages"> <Messages data = {messages}> </ Messages> </ ul> <ul id = "online"> & # x1f310; : </ UL> <div id = "sendform"> <form id = "messageform" style = {{display: 'flex'}}> <input id = "m" /> <button type = "submit"> Отправить сообщение </ button> </ Форма> </ DIV> </ Раздел> ): ( // ...Последние штрихи
У нас есть еще несколько настроек, чтобы завершить наше приложение чата. В частности, нам все еще нужно:
- Компонент для отображения людей, которые онлайн
- Хук useImmer для него с прослушивателем сокета
- Обработчик отправки сообщений с соответствующими сокетами
Все это основано на том, что мы уже рассмотрели. Я собираюсь добавить полный код файла App.js, чтобы показать, как все сходится.
// App.js импортировать React, {useState, useEffect} из'act '; импортировать useSocket из 'use-socket.io-client'; import {useImmer} из 'use-immer'; import './index.css'; const Messages = props => props.data.map (m => m [0]! == ''? (<li> <strong> {m [0]} </ strong>: <div className = "innermsg" > {m [1]} </ div> </ li>): (<li className = "update"> {m [1]} </ li>)); const Online = props => props.data.map (m => <li id = {m [0]}> {m [1]} </ li>); экспорт по умолчанию () => { const [room, setRoom] = useState (''); const [id, setId] = useState (''); const [socket] = useSocket ('<https://open-chat-naostsaecf.now.sh>'); Socket.connect (); const [messages, setMessages] = useImmer ([]); const [онлайн, setOnline] = useImmer ([]); useEffect (() => { socket.on ('очередь сообщений', (ник, сообщение) => { setMessages (draft => { draft.push ([ник, сообщение]) }) }); socket.on ('update', message => setMessages (draft => { draft.push ([ '', сообщение]); })) socket.on ('список людей', люди => { let newState = []; для (пусть человек в людях) { newState.push ([люди [человек] .id, люди [человек] .nick]); } setOnline (проект => {draft.push (... NewState)}); console.log (онлайн) }); socket.on (надстройки человека ', (ник, ID) => { setOnline (draft => { draft.push ([ID, ник]) }) }) socket.on ( 'удалить-человек', идентификатор => { setOnline (draft => draft.filter (m => m [0]! == id)) }) socket.on ('сообщение чата', (ник, сообщение) => { setMessages (draft => {draft.push ([ник, сообщение])}) }) }, 0); const handleSubmit = e => { e.preventDefault (); const name = document.querySelector ('# name'). value.trim (); const room_value = document.querySelector ('# room'). value.trim (); if (! name) { уведомление о возврате («Имя не может быть пустым»); } SETID (имя); setRoom (document.querySelector ( '# номер') value.trim ().); console.log (номер) socket.emit ("join", name, room_value); }; const handleSend = e => { e.preventDefault (); const input = document.querySelector ('# m'); if (input.value.trim ()! == '') { socket.emit ('сообщение чата', input.value, комната); input.value = ''; } } вернуть идентификат <section style = {{display: 'flex', flexDirection: 'row'}}> <ul id = "messages"> <Data messages = {messages} /> </ ul> <ul id = "online"> & # x1f310; : <Online data = {online} /> </ ul> <div id = "sendform"> <form onSubmit = {e => handleSend (e)} style = {{display: 'flex'}}> <input id = "m" /> <button style = {{width: '75px'}} type = "submit"> Send </ button> </ Форма> </ DIV> </ Раздел> ): ( <div style = {{textAlign: 'center', поле: '30vh auto', ширина: '70% '}}> <form onSubmit = {event => handleSubmit (event)}> <input id = "name" обязательный заполнитель = "Как вас зовут .." /> <br /> <input id = "room" placeholder = "Какая у вас комната .." /> <br /> <button type = "submit"> Submit </ button> </ Форма> </ DIV> ); };Завершение
Это оно! Мы вместе создали полнофункциональное приложение для группового чата! Как это круто? Полный код проекта можно найти здесь, на GitHub.
То, что мы рассмотрели в этой статье, представляет собой лишь представление о том, как React Hooks может повысить вашу производительность и помочь вам создавать мощные приложения с помощью мощных инструментов интерфейса. В этом всеобъемлющем учебнике я создал более надежное приложение для чата . Следуйте, если вы хотите подняться дальше с React Hooks.
Теперь, когда у вас есть практический опыт работы с React Hooks, используйте полученные знания, чтобы получить еще больше практики! Вот несколько ид
Комментариев нет:
Отправить комментарий