предисловие
В настоящее время существует множество руководств по началу работы с React, больших и малых, и они познакомят вас с некоторымиосновная концепцияа такжеПрименение, который удобно перенесет вас в мир React. Но помимо подробного описания основных понятий, эта статья поможет вам перейти от понимания React кзнакомыйЭтопринцип.
Напоминание: поскольку эта статья знакома с принципом, поэтому здесьПодходящееВ том числе: принцип **реакцииСтуденты, которые заинтересованы, но еще не начали ипопал в яму реагироватьодноклассники. React — это своего рода мысль, я надеюсь, что, интерпретируя ее, я смогу привлечь какие-то идеи и внести некоторыеВеселое ** мышление.
система событий
Механизм реализации синтетических событий
Под капотом React есть две основные вещи, связанные с синтетическими событиями: делегирование событий и автоматическая привязка.
1. Делегация мероприятия
Прежде чем использовать события React, обязательно ознакомьтесь с его механизмом делегирования событий. Он не привязывает напрямую обработчики событий к реальным узлам, но привязывает все события к самому внешнему слою структуры, используя унифицированный прослушиватель событий, который поддерживает карту для сохранения прослушивателей и обработчиков событий внутри всех компонентов. Когда компонент монтируется или размонтируется, он просто вставляет или удаляет какие-то объекты в этот унифицированный прослушиватель событий, когда происходит событие, оно сначала обрабатывается этим унифицированным прослушивателем событий, а затем находит в карте настоящий обработчик событий и вызывает его. Это упрощает механизм обработки и повторного использования событий, а также значительно повышает эффективность.
2. Автоматическая привязка
В компонентах React контекст каждого метода указывает на экземпляр компонента, то есть он автоматически привязывается к текущему компоненту. И React также кэширует такие ссылки для оптимизации процессора и памяти. При использовании классов ES6 или чистых функций эта автоматическая привязка больше не существует, и нам нужно вручную реализовать эту привязку.
Мы использовали функцию стрелки для автоматической обработки привязки.
import React, { Component } from 'react';
class App extends Component {
const handleClick = (e) => {
console.log(e);
};
render() {
return <button onClick={this.handleClick}>Test</button>;
}
}
или
import React, { Component } from 'react';
class App extends Component {
handleClick(e) {
console.log(e);
}
render() {
return <button onClick={() => this.handleClick()}>Test</button>
}
}
Сравнение синтетических событий React с нативными событиями JavaScript
Ниже мы сравниваем синтетические события React и нативные события JavaScript по четырем аспектам.
1. Распространение событий и предотвращение распространения событий
Распространение встроенных в браузер событий DOM можно разделить на 3 этапа: этап захвата событий, вызов обработчика событий самого целевого объекта и всплывающая подсказка событий. Захват событий будет предпочтительно вызывать прослушиватель событий, привязанный к самому внешнему элементу дерева структуры, а затем по очереди вызывать внутренний, пока не будет вызван прослушиватель событий на целевом элементе. Обработчик события захвата может быть зарегистрирован для элемента e, если для третьего параметра e.addEventListener() установлено значение true, и он вызывается на первом этапе распространения события. Кроме того, захват событий не является универсальным методом и не может использоваться в браузерах ниже IE9. Всплытие событий, с другой стороны, противоположно захвату событий, оно распространяет события от целевого элемента наружу, изнутри наружу к самому внешнему слою.
Видно, что значение захвата событий при разработке программ невелико, и более фатальной проблемой является его совместимость. Поэтому синтетические события React не реализуют захват событий, а только поддерживают механизм всплытия событий. Этот метод проектирования API является унифицированным и лаконичным и соответствует «28 принципам».
Чтобы предотвратить распространение собственного события, вам нужно использовать e.preventDefault() , но для браузеров, которые не поддерживают этот метод (ниже IE9), вы можете использовать только e.cancelBubble = true для предотвращения. В синтетических событиях React просто используйте e.prevent-Default() .
2. Тип события
Типы событий для синтетических событий React являются подмножеством собственных типов событий JavaScript.
3. Метод привязки событий
Под влиянием стандартов DOM существует множество способов привязки собственных событий браузера, как показано ниже.
-
Привязать непосредственно к элементу DOM:
<button onclick="alert(1);">Test</button>
-
В JavaScript привязка достигается путем присвоения значений свойствам события элемента:
el.onclick = e => { console.log(e); }
-
Связывание достигается с помощью функции прослушивания событий:
el.addEventListener('click', () => {}, false); el.attachEvent('onclick', () => {});
Напротив, привязка синтетических событий React намного проще:
<button onClick={this.handleClick}>Test</button>
4. Объект события
Существуют различия между собственными объектами событий DOM в соответствии со стандартом W3C и стандартом IE. В более ранних версиях браузеров IE вы можете использовать только window.event для получения объекта события. В системе синтетических событий React такой проблемы совместимости нет, и объект синтетического события можно получить в обработчике события.
обработка стиля
CSS Modules
Ниже мы подробно расскажем о модулях CSS.
1. Какие проблемы с модульностью CSS?
Важной модульной вещью CSS является решение следующих двух вопросов: импорт и экспорт стилей CSS. Импортируйте спрос на гибкое повторное использование кода, чтобы иметь возможность скрыть внутреннюю область при экспорте, чтобы избежать глобального загрязнения. Sass, Less, PostCSS и другие попытки решить проблему слабых навыков программирования на CSS, но это не решило проблему модульности. Инженер Facebook Vjeux бросает ряд связанных с CSS проблем, с которыми React столкнулся в процессе разработки, в сочетании с фактической разработкой проблемы заключаются в следующем.
- глобальное загрязнение: CSS использует механизм глобального селектора для установки стилей, преимуществом которого является простота переопределения стилей. Недостатком является то, что все стили являются глобальными, стили могут быть перезаписаны по ошибке, что приведет к очень уродливому !important, даже встроенному !important и сложномутаблица подсчета веса селектора, уменьшите вероятность ошибки и стоимость использования. Shadow DOM в стандарте Web Components может полностью решить эту проблему, но он полностью локализует стиль, делая невозможным внешнее переписывание стиля и теряя гибкость.
- путаница в именах: Из-за проблемы глобального загрязнения, чтобы избежать конфликтов стилей во время совместной разработки с несколькими людьми, селекторы становятся все более и более сложными, и легко формировать разные стили именования, которые трудно унифицировать. Чем больше стилей, тем более запутанным будет наименование.
- Неполное управление зависимостями: Компоненты должны быть независимы друг от друга.При импорте компонента следует импортировать только необходимые ему стили CSS. Текущая практика заключается в том, чтобы вводить свой CSS в дополнение к JavaScript, и для Saas/Less сложно составлять отдельный CSS для каждого компонента, а введение CSS для всех модулей расточительно. Модульность JavaScript очень зрелая, это хорошее решение, позволяющее JavaScript управлять зависимостями CSS, и css-loader webpack обеспечивает эту возможность.
- не может делиться переменными: для сложных компонентов, использующих JavaScript и CSS для совместной обработки стилей, некоторые переменные являются избыточными в JavaScript и CSS, а предварительно скомпилированные языки не предоставляют возможности совместного использования переменных между JavaScript и CSS.
- Сжатие кода не завершено: Из-за неопределенности мобильной сети требования к сжатию CSS в современных инженерных проектах достигли извращенного уровня. Многие инструменты сжатия преобразуют 16px в 1pc, чтобы сэкономить байт, но это ничего не может сделать для очень длинных имен классов.
Вышеуказанные проблемы не могут быть решены одним лишь CSS, если CSS управляется с помощью JavaScript, их можно решить очень легко. Следовательно, решение, данное Vjuex, является полным.CSS in JS, но это равносильно полному отказу от CSS и написанию CSS с отображением хэшей на JavaScript, но такой подход был немного радикальным, пока не появились CSS Modules.
2. Модульное решение CSS Modules
Модули CSS используют ICSS для решения двух проблем импорта и экспорта стилей, соответствующих двум новым псевдоклассам :import и :export соответственно:
:import("path/to/dep.css") {
localAlias: keyFromDep;
/* ... */
}
:export {
exportedKey: exportedValue;
/* ... */
}
Однако использовать эти два ключевых слова напрямую в программе слишком громоздко, и они редко используются напрямую в проекте.Что нам нужно, так это возможность управлять CSS с помощью JavaScript. В сочетании с css-загрузчиком webpack вы можете определять стили в CSS и импортировать их в файлы JavaScript.
-
Включить CSS-модули
Код для включения модулей CSS выглядит следующим образом:
// webpack.config.js css?modules&localIdentName=[name]__[local]-[hash:base64:5]
Добавьте модули для включения, где localIdentName — соглашение об именах для установки стиля сборки.
Для студентов, которые создают проекты с приложением create-react-app, npm run eject может открыть конфигурацию.
Давайте посмотрим непосредственно на то, как ссылаться на CSS и как webpack преобразует имена классов:
/* components/Button.css */ .normal { /* normal 相关的所有样式 */ } .disabled { /* disabled 相关的所有样式 */ }
Сохраните приведенный выше CSS, а затем используйте метод импорта, чтобы сослаться на него в файле JavaScript:
/* components/Button.js */ import styles from './Button.css'; console.log(styles); // => // Object { // normal: 'button--normal-abc5436', // disabled: 'button--disabled-def884', // } buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`
Мы видим, что окончательный сгенерированный HTML выглядит так:
<button class="button--normal-abc5436"> Processing... </button>
Обратите внимание, что button--normal-abc5436 — это имя класса, автоматически сгенерированное модулями CSS в соответствии с localIdentName.
скажем, где abc5436 — код последовательности, сгенерированный по заданному алгоритму. После такой запутанности имя класса в основном Единственный, который значительно снижает вероятность переопределения стиля в вашем проекте. В то же время измените правила в производственной среде, чтобы генерировать более короткие имена классов, Может улучшить коэффициент сжатия CSS.
Модули CSS обрабатывают имена классов в CSS и используют объекты для сохранения исходного класса и запутанного класса. Переписка. С помощью этих простых процессов модули CSS достигают следующих целей:
-
Все стили локализованы, разрешая конфликты имен и глобальное загрязнение;
-
Гибко настраиваются правила генерации имен классов, что позволяет использовать их для сжатия имен классов;
-
Просто обратитесь к JavaScript компонента, и вы сможете получить весь JavaScript и CSS компонента;
-
Это по-прежнему CSS, и стоимость обучения практически нулевая.
-
локальный стиль по умолчанию
После использования модулей CSS это эквивалентно добавлению :local к каждому имени класса для достижения локализации стилей. Если мы хотим переключиться в глобальный режим, мы можем использовать пакет :global. Пример кода выглядит следующим образом:
.normal { color: green; } /* 以上与下面等价 */ :local(.normal) { color: green; } /* 定义全局样式 */ :global(.btn) { color: red; } /* 定义多个全局样式 */ :global { .link { color: green; } .box { color: yellow; } }
-
Используйте композы для комбинированного стиля
Для повторного использования стилей CSS-модули предоставляют только один способ — компоновку. Пример кода выглядит следующим образом:
/* components/Button.css */ .base { /* 所有通用的样式 */ } .normal { composes: base; /* normal 其他样式 */ } .disabled { composes: base; /* disabled 其他样式 */ } import styles from './Button.css'; buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`
Результирующий HTML становится:
<button class="button--base-abc53 button--normal-abc53"> Processing... </button>
Поскольку .base объединяется с .normal, скомпилированный normal становится двумя классами.
Кроме того, стили из внешних файлов можно комбинировать с помощью композиций:
/* settings.css */
.primary-color {
color: #f40;
}
/* components/Button.css */
.base { /* 所有通用的样式 */ }
.primary {
composes: base;
composes: $primary-color from './settings.css';
/* primary 其他样式 */
}
Для большинства проектов с композицией прекомпилированный процессор больше не нужен. Но если вы хотите использовать его, поскольку composes не является стандартным синтаксисом CSS, во время компиляции будет сообщено об ошибке.В настоящее время вы можете использовать только собственный синтаксис препроцессора для повторного использования стилей.
-
трюк с именами классов
Соглашение об именах для модулей CSS расширено из БЭМ. БЭМ делит имена стилей на 3 уровня, как показано ниже.
- Блок: соответствует имени модуля, например Диалог.
- Элемент: соответствует имени узла «Кнопка подтверждения» в модуле.
- Модификатор: соответствует состояниям, связанным с узлом, таким как отключено и подсвечено.
Окончательный класс, полученный с помощью БЭМ, называетсяdialog__confirm-button--highlight. Двойные символы __ и -- используются, чтобы отличить их от разделителей между словами внутри блока. Хотя это может показаться странным, БЭМ используется во многих крупных проектах.
Имя файла CSS в модулях CSS просто соответствует имени блока, просто обратите внимание на элемент и модификатор. То, как БЭМ соответствует модулям CSS, таково:
/* .dialog.css */ .ConfirmButton--disabled {}
Мы также не можем следовать полному соглашению об именах и использовать маленький регистр верблюда, чтобы соединить Блок и Модификатор:
/* .dialog.css */ .disabledConfirmButton {}
-
Реализовать совместное использование переменных CSS и JavaScript
Упомянутое выше ключевое слово :export может экспортировать переменные CSS в JavaScript, например:
/* config.scss */ $primary-color: #f40; :export { primaryColor: $primary-color; } /* app.js */ import style from 'config.scss'; // 会输出 #F40 console.log(style.primaryColor);
3. Советы по использованию модулей CSS
Модули CSS — это вычитания из существующего CSS. Для достижения простоты и управляемости автор рекомендует следовать следующим принципам:
- Не используйте селекторы, используйте только имена классов для определения стилей;
- Вместо объединения нескольких классов используйте только один класс для определения всех стилей;
- Все стили повторно используются в композициях;
- Не вложенный.
Первые два принципа равносильны ослаблению самой гибкой части стиля, которую трудно принять новичкам. Первое трудно практиковать Немного, но когда во втором элементе слишком много состояний модуля, количество классов будет увеличиваться в геометрической прогрессии.
Причина, по которой он говорит «рекомендуется», заключается в том, что CSS-модули не заставляют нас это делать. Это звучит противоречиво. Из-за глубокого наследия большинства проектов CSS слишком много ограничений означают увеличение затрат на миграцию и стоимость внешнего сотрудничества. Первоначальное использование определенно потребует некоторых компромиссов. К счастью, модули CSS делают это очень хорошо. Ниже мы перечисляем некоторые часто задаваемые вопросы.
(1) Что, если я использую несколько классов для элемента?
Стиль актуален до сих пор.
(2) Что, если я использую класс с таким же именем в файле стиля?
Хотя эти классы с одинаковыми именами могут быть случайными кодами после компиляции, они по-прежнему имеют одно и то же имя.
(3) Что, если я использую селекторы идентификаторов, псевдоклассы, селекторы тегов и т. д. в файле стиля?
Все эти селекторы не будут преобразованы и появятся в скомпилированном CSS как есть. То есть модули CSS будут преобразовывать только стили, связанные с именами классов.
4. Модули CSS в сочетании с практикой исторических проектов
Хорошее техническое решение должно быть не только мощным и крутым, но и обеспечивать плавную миграцию существующих проектов.Модули CSS здесь. Очки очень гибкие.
-
Как внешние стили переопределяют локальные стили
Когда создается запутанное имя класса, конфликты имен могут быть разрешены, но, поскольку окончательное имя класса нельзя предсказать, его нельзя переопределить с помощью общего селектора. Наша текущая практика в проекте заключается в том, чтобы добавить атрибут data-role к ключевым узлам компонента, а затем переопределить стиль через селектор атрибутов:
// dialog.js return ( <div className={styles.root} data-role="dialog-root"> <a className={styles.disabledConfirm} data-role="dialog-confirm-btn">Confirm</a> ... </div> ); // dialog.css [data-role="dialog-root"] { // override style }
Поскольку модули CSS только преобразуют селекторы класса, нет необходимости добавлять: глобальные для селекторов атрибутов здесь.
-
Как сосуществовать с глобальными стилями
Интерфейсные проекты неизбежно будут включать normalize.css или другие глобальные файлы CSS.Использование веб-пакета может обеспечить гармоничное сосуществование глобальных стилей и локальных стилей модулей CSS. Ниже приведена часть веб-пакета кода конфигурации, используемого в конкретном проекте:
module: { loaders: [{ test: /\.jsx?$/, loader: 'babel', }, { test: /\.scss$/, exclude: path.resolve(__dirname, 'src/styles'), loader: 'style!css?modules&localIdentName=[name]__[local]!sass?sourceMap=true', }, { test: /\.scss$/, include: path.resolve(__dirname, 'src/styles'), loader: 'style!css!sass?sourceMap=true', }] } /* src/app.js */ import './styles/app.scss'; import Component from './view/Component' /* src/views/Component.js */ import './Component.scss';
Структура каталогов следующая:
src ├── app.js ├── styles │ ├── app.scss │ └── normalize.scss └── views ├── Component.js └── Component.scss
Таким образом, все глобальные стили можно импортировать в src/styles/app.scss, а стили во всех остальных каталогах (включая src/views) являются локальными.
Модули CSS — отличное решение проблем модульности, с которыми в настоящее время сталкивается CSS. Он поддерживает использование предварительно скомпилированных языков, может в полной мере использовать существующие технологии, а также гибко сопоставляться с глобальными стилями. Реализация CSS-модулей также проста и может быть перенесена с небольшими затратами, когда в будущем появится стандартное решение.
5. Модули CSS в сочетании с практикой React
Просто используйте имя класса в CSS непосредственно в className:
/* dialog.css */
.root {}
.confirm {}
.disabledConfirm {}
/* dialog.js */
import React, { Component } from 'react';
import classNames from 'classnames';
import styles from './dialog.css';
class Dialog extends Component {
render() {
const cx = classNames({
confirm: !this.state.disabled,
disabledConfirm: this.state.disabled,
});
return (
<div className={styles.root}>
<a className={styles[cx]}>Confirm</a>
...
</div>
);
}
}
Обратите внимание, что имя класса, соответствующее самому внешнему узлу компонента, обычно называется root.
Обработка стилей в React не сильно отличается от других библиотек представлений, в основном в прямом манипулировании стилями или косвенном манипулировании стилями путем манипулирования именем класса. И глубокая интеграция с модулями CSS может быть главной особенностью React. Представьте себе концепцию модульности CSS, и мы приблизимся к мечте о полноценной веб-компонентизации.
Если вы не хотите вводить **styles., вы можете использовать библиотеку react-css-modules. Это позволяет избежать повторного ввода стилей ** в виде компонентов более высокого порядка.. Перепишем приведенный выше пример:
import React, { Component } from 'react';
import classNames from 'classnames';
import CSSModules from 'react-css-modules';
import styles from './dialog.css';
class Dialog extends Component {
render() {
const cx = classNames({
confirm: !this.state.disabled,
disabledConfirm: this.state.disabled,
});
return (
<div styleName="root">
<a styleName={cx}>Confirm</a>
...
</div>
);
}
}
export default CSSModules(Dialog, styles);
Кроме того, по сравнению с оригинальными модулями CSS есть несколько преимуществ:
- Мы больше не фокусируемся на том, используют ли использование верблюда названного имени класса;
- Нам не нужно связывать объект стиля каждый раз, когда мы используем модули CSS;
- Используя CSS-модули, легко использовать :global для решения особых случаев, используя react-css-modules, можно записать как `
className="global-css" styleName="local-module">`, эта форма легко соответствует глобальной и локальной;
- Мы получаем предупреждение, когда имя стиля связано с неопределенными модулями CSS;
- Мы можем принудительно использовать один CSS-модуль.
Справочная статья
благодарный
- Сеть источника изображения.
- Если в тексте есть ошибки, критикуйте и исправьте их в комментариях.
- Если эта статья была вам полезна, ставьте лайк и поддержите ее! Спасибо за прочтение.