Эй, давайте построим лампочку!
Или, по крайней мере, включение/выключение часть лампочки … Toggle Switch является супер общим элементом пользовательского интерфейса для указывает, является ли некоторая функция активна или нет.
Подобные переключатели на самом деле так распространены, это было бы неплохо, если бы они были своими собственными HTML элемент…
Ну, сквозь магию веб-компоненты На самом деле это возможно сделать это!
Моя цель – проиллюстрировать один способ, как оба построить и Тест веб-компонент. Однако вместо того, чтобы идти пошаговый «вот код для создания тумблера», мы будем пострастно (в некотором смысле) собирать лампочку, представляющую Ключевые аспекты для создания многоразового веб-компонента , который применяется при создании любой многоразовый элемент.
Как мы собираем эту лампочку кусочка, мы также сделаем Toggle-Switch Компонент, который мы знаем и люблю!
Так что все, что сказано, давайте построим лампочку!
- Изобретать лампочку
- Семантика: схема
- Доступность: шапка
- Атрибуты: контактные провода
- JavaScript: Нить
- События: Инертный газ
- Стиль: Глобус
- Резюме
- Полный код
Для битов кода я получу некоторое знакомство со следующим:
- HTML, CSS и JavaScript (см. Начало работы с Интернетом )
- С использованием NPM Для установки зависимостей ( видеть Руководство для новичка к использованию NPM )
- Тестовый код с кодом (см. Как начать тестирование подразделения )
Ключевые вынос
Вот немного TL; DR Показывая все большие точки, чтобы подумать о создании веб-компонентов.
- Веб-компоненты Создать Новая семантика через пользовательские элементы.
- Доступны Компоненты позволяют несколько методов взаимодействия.
- Атрибуты Поверхность Важное состояние, конфигурация и нюанс смысл.
- Функции JavaScript разоблачить ключевое поведение элемента и действия.
- События сообщите ключевые действия или изменения для других элементов для реагирования на.
- Стиль Предварительно доступен через тщательно выбранные переменные CSS и теневые детали.
И вот все идеи кодирования веб-компонентов, которые касаются реализации составная часть. Посмотрите, как мы используем их для создания компонента или просто ссылаться на ресурсы ниже!
- Создание веб-компонентов как профессионал.
- @ Open-WC/тестирование Обеспечивает полезные тестирование помощников для набора нашего компонента на веб-странице.
- @ Веб/тест-бегун Запускает наши тесты в реальном браузере.
- Тестовые приспособления Установите элемент на странице для тестирования.
- ConnectedCallback Инициализирует элемент при вставке на страницу.
- Атрибуты и свойства Может быть установлен на пользовательских элементах.
- Наблюдательные материалы и AttributeChangedCallback реагировать на изменения в атрибутах.
- DisconnectedCallback Очищает после элемента, когда он удален из документа.
- OneeVent Испытания, которые произошло событие.
- Пользовательские события Пусть вы отправляете события, специфичные для вашего компонента.
- Тень Дом Инкапсулирует структуру, стиль и поведение из общего документа.
- Теневые детали Разрешить внешние CSS настроить определенные внутренние элементы веб-компонента.
- : хозяин Позволяет стимулировать сам веб-компонент из своей тени DOM.
Я также создал Веб-компонент Вы можете установить и использовать на своих проектах или использовать в качестве ссылки:
Auroratide/Toggle-Switch
Изобретать лампочку
В каждом разделе я буду:
- Обсудите аспект веб-компонентов, в том числе почему это важно
- Примените этот аспект, чтобы построить
Компонент с кодом
Семантика: схема
Все хорошие изобретения начинаются с рисунком, показывающей дизайн! Перед созданием веб-компонента нам нужно подумать о Почему Мы строим это.
Ну, что такое веб-компонент так или иначе?
Чтобы ответить на этот вопрос, нам нужно ответить на другой вопрос: что такое Блок цитата ?
Ну, это довольно распространено для таких статей, как это захотеть процитировать кого-то или что-то, например, Thomas Edison:
Чтобы придумать, вам нужно хорошее воображение и кучу мусора.
Вы можете сказать, что это цитата своего рода по его форматированию. И, к счастью, код, чтобы сделать это произошло довольно просто:
To invent, you need a good imagination and a pile of junk.
Бит – это тег HTML со специальным значением. Когда разработчик использует его, они объявляют, что следующий текст является раздел, который цитируется из другого источника
.
Вы видите, для достижения форматирования цитаты блока мне не нужно было использовать Блокнота элемент вообще. Я мог бы использовать какой-то другой HTML-элемент и заставил его выглядеть как цитату, но, хотя это может быть полезно для визуальных читателей, это не было бы полезным ботам или читателям, которые полагаются на вспомогательные технологии, чтобы прочитать громкую страницу.
Что вспомогательные технологии ? У многих людей есть недостатки, которые препятствуют их использованию сайта общего пользования, и поэтому они полагаются на вспомогательные технологии для перемещения в Интернете. Примером такой технологии – это экран считывателя, который устно считывает страницу, настолько нарушенные наглядят, люди могут понять содержание.
Другими словами, что Блокнота тег имеет особый смысл, называемый семантика И эти семантики позволяют что-либо читать страницу, чтобы понять, что представляет содержимое. Как и блочные цитаты, большинство HTML-элементов имеют специальную семантику, связанную с ними.
ОК Timothy, что делать блочные цитаты с веб-компонентами?
Итак, наша цель – создать новый HTML-элемент, Отказ Имея в виду, что большинство элементов HTML имеют связанную семантику, это приводит нас к интересному пониманию:
Создание веб-компонентов Новая семантика через пользовательские HTML элементы.
Это обычно не так, как я вижу описанные веб-компоненты. Обычно веб-компоненты рассматриваются в разработчике, ориентированных на термины, такие как повторное использование и инкапсуляция. Хотя это действительно великие цели и результаты, обрамление веб-компонента с точки зрения его семантики, действительно помогает захватить, почему мы это делаем и что это будет делать.
Итак, когда дело доходит до создания нового компонента, первый шаг – понять, что это цель И это поможет вам решить, каковы его обязанности и объем.
Для нашего Компонент, это довольно похоже на нативный флажок HTML, но с одним различием: в то время как флажок либо проверяется, либо не проверяется, наш элемент коммутатора является либо ON или OFF , который тонко отличается семантическим.
Кроме того, флажки имеют третью ” неопределенный «Значение, которое не проверяется, ни не проверено. Такое третье значение не имеет смысла для переключателя включения/выключения.
Как только мы определили то, что и почему веб-компонента, мы можем создать немного лесов! Начнем с компонента скелета:
// toggle-switch.js
export class ToggleSwitch extends HTMLElement {
static elementName = 'toggle-switch'
constructor() {
super()
}
}
window.customElements.define(ToggleSwitch.elementName, ToggleSwitch)
customelements.define Глобальная функция – это то, что на самом деле определяет веб-компонент, и он должен поставляться как с именем элемента, так и классом, расширяющим Htmlelement Отказ Все наши возможные функциональные возможности пойдут в TogglesWitch класс.
Что касается тестирования, мы собираемся полагаться на два библиотека:
@ Open-WC/тестирование: Библиотека тестирования, предоставляющая полезные помощники для монтажа нашего компонента@ Веб/тест-бегун: Программа, которая фактически запускает наши тесты против настоящего браузера
Я подчеркиваю бит «против реального браузера», потому что это дает максимальную уверенность в том, что элемент, как оно ведет себя в тестах, будет таким же, как оно ведет себя в дикой природе. Это противостоит использовать что-то вроде JSDOM , который классически имел плохую поддержку для веб-компонентов.
Эти библиотеки могут быть установлены с NPM:
npm i -D @open-wc/testing @web/test-runner
С этим все, что нам нужно сейчас – это файл теста скелета и возможность запустить указанный тест:
// toggle-switch.spec.js
import { expect } from '@open-wc/testing'
import './toggle-switch.js'
describe('toggle-switch', () => {
it('works', () => {
expect(1).to.equal(1)
})
})
Запуск теста:
wtr --node-resolve ./**/*.spec.js
И с этим мы наконец готовы начать строить наши составная часть!
Кодовые функции:
- Создание веб-компонентов как профессионал.
- @ Open-WC/тестирование Обеспечивает полезные тестирование помощников для набора нашего компонента на веб-странице.
- @ Веб/тест-бегун Запускает наши тесты в реальном браузере.
Доступность: шапка
Крышка лампочки – это где это Доступ его сила. Поэтому крышка представляет Доступность Действительно
Доступность Это практика создания вещей, которые можно использовать как можно большему количеству людей, независимо от способности или инвалидности. Например, если слепой человек полагается на экран-ридер, чтобы прочитать страницу вслух к ним, то когда они достигают переключателя Toggle, они должны быть в курсе того, что элемент действительно является коммутатором.
Это довольно широкая тема, которую я не могу полностью скрыть здесь, но когда дело доходит до веб-компонентов, есть некоторые ключевые вопросы, которые мы можем задать:
- Что роль Или набор ролей делает наш компонент?
- Как читатели знают, что такое этот компонент и как его использовать?
- Каким образом люди могут использовать этот компонент, и нам нужно сделать что-то особенное для размещения тем?
Доступен Компоненты позволяют несколько методов взаимодействия.
Лично мне нравится использовать доступность в качестве отправной точки, так что хорошие практики встроены в компонент раньше, а не позже. Давайте применим это конкретно к тумблему!
Для кодирования давайте начнем с ответами на ключевые вопросы:
- Какую роль или набор ролей служат наш компонент?
Wai-Aria Определяет Роль называется «переключатель» Что на самом деле идеально подходит для нашего компонента. Если мы укажем эту роль на нашем компонент, вспомогательные технологии, такие как считыватели экрана, могут сообщить своим слушателям, что они могут переключить что-то и выключить.
Что Вай-ария ? Вай-ария Стенгируются для доступных богатых интернет-приложений, и она Essically предоставляет основу для продвинутого веб-сайта более доступных для людей с ограниченными возможностями.
- Как читатели знают, что такое этот компонент и как его использовать?
Иногда необходимо особую маркировку, чтобы правильно информировать людей, которые не могут видеть элемент, что это такое. В нашем случае мы можем полагаться на роль коммутатора, чтобы сделать это: когда устройство Reader сталкивается с элементом, помеченным в качестве коммутатора, он должен сообщить, что элемент представляет собой переключатель без нас, чтобы сделать какую-либо дополнительную работу!
- Каким образом люди могут использовать этот компонент, и нам нужно сделать что-то особенное для размещения тем?
Помимо нажатия на коммутатор, некоторые люди могут не иметь или не могут использовать мышь, и, следовательно, переключатель должен быть интерактивным через клавиатуру.
Принимая эти два опасения вместе, это означает:
- Мы должны установить
рольатрибутПереключательОтказ - Мы должны сделать элемент сосредоточен, который можно сделать, установив
Tabindex(см. атрибут tabindex ).
Позаботиться о первом предмете, давайте сначала Написать тест :
import { fixture, expect } from '@open-wc/testing'
describe('accessibility', () => {
it('default role', async () => {
const el = await fixture(` `)
expect(el.getAttribute('role')).to.equal('switch')
})
})
Этот тест делает две вещи:
- Создать Крепеж который содержит наши новые
Toggle-Switchэлемент. - Утверждать, является ли доступная роль элемента выключателем.
Крепеж Функция, предоставленная @ Open-WC/тестирование довольно нефте! Он по существу устанавливает HTML-документ и помещает наш элемент на страницу, что позволяет нам связываться и осмотреть его.
Наш тест подразумевает, что мы должны настроить наш элемент, чтобы немедленно иметь роль «переключателя». Для этого мы полагаемся на метод жизненного цикла называется ConnectedCallback :
export class ToggleSwitch extends HTMLElement {
connectedCallback() {
this.setAttribute('role', 'switch')
}
}
Что методы жизненного цикла ? Как и, как все живые существа рождаются и в конечном итоге умирают, элементы на веб-странице могут прийти и пойти. Методы жизненного цикла представляют ключевые моменты для элемента, например, когда он вставлен на страницу, удален со страницы или обновляется.
ConnectedCallback Функция вызывается каждый раз, когда элемент вставлен на страницу, что отлично подходит для инициализации!
Что отличается между CondentCallback И конструктор? Конструктор называется, когда элемент создан в первый раз, тогда как то CondentCallback называется сразу после добавления элемента на страницу. Один из способов думать об этом, если такой же Элемент добавляется и удален с страницы снова и снова и снова, конструктор вызывается только один раз, тогда как CondentCallback называется каждый раз, когда он добавляется обратно на страницу. Вот хорошее резюме того, что делать с Конструктор против подключенной клавиши .
Для нашего требования к таббельным требованиям тест и инициализация очень похожи. Настройка Tabindex = "0" Это все, что нужно, чтобы сделать элемент Tabbable, позволяя пользователям клавиатуры доступа к нашему коммутатору!
export class ToggleSwitch extends HTMLElement {
connectedCallback() {
this.setAttribute('role', 'switch')
this.setAttribute('tabindex', '0')
}
}
Теперь, для нашей роли Арии, есть на самом деле немного больше Нам нужно сделать для нашего компонента, чтобы на самом деле быть доступным выключателем. Удобно, мы будем говорить об этом в самом следующем разделе …
Кодовые функции:
- Тестовые приспособления Установите элемент на странице для тестирования.
- ConnectedCallback Инициализирует элемент при вставке на страницу.
Атрибуты: контактные провода
Далее на нашей лампочке являются контактными проводами, которые питают питание части, которая загорается. Это будет представлять атрибуты Действительно
Элементы HTML имеют атрибуты которые в основном рассказывают больше о текущем состоянии элемента или как он должен работать. Например, Элемент имеет атрибут под названием цитировать который является ссылкой на источник цитаты.
If the cite attribute is present, it must be a valid URL. . .
Таким образом, пользовательские элементы также могут разоблачать атрибуты! Их три ключевых использования предназначены для:
- Государство : Например, начальная или текущая стоимость элемента
- Конфигурация : Например, ли элемент отключен, имеет входные границы и так далее
- Нюанс смысл : Указание более подробной информации о семантической цене элемента
Атрибуты Поверхность Важное состояние, конфигурация и нюанс смысл.
Касательно нюанс смысл хороший пример cite атрибут включен блокировка . У него нет функциональной цели, а также не настраивает элемент никак. Это просто усиливает смысл элемента: это не просто какое-либо цитата, а цитата из определенного источника.
Сделать Элемент, есть хотя бы одно важное состояние, которое мы хотим передавать с атрибутом: включен ли переключатель или выключен. Давайте следуем по этим трем шагам для создания этого атрибута:
- Определить Имя и Разрешенные значения для атрибута.
- Установите Недвижимость для атрибута.
- Определить ли Изменить В атрибуте триггеры изменение элемента.
Чтобы подражать немного, как работает входной элемент Checkbox Vanilla, мы назовем наш атрибут проверено И это будет булевой атрибут, что означает, что его наличие или отсутствие будет представлять собой истинно или ложное соответственно.
Установка Недвижимость Для класса элемента существенно заявляет, что атрибут важен. По правде говоря, любой элемент может иметь любой атрибут, поэтому, создав свойство, мы общаемся, что проверено важно для тумблера.
class ToggleSwitch extends HTMLElement {
get checked() {
return this.hasAttribute('checked')
}
set checked(value) {
this.toggleAttribute('checked', value)
}
}
И интересный вопрос: смена в проверено требуют изменения на элементе?
Я могу подумать как минимум две вещи, которые должны измениться, когда проверено Атрибут добавляется или удален из переключателя Toggle:
- Переключатель должен оживить (но мы доберемся до этого, когда обсудим styling )
-
Проверено ARIAАтрибут должен отражатьпровереноатрибут.
… что ?
Напомним из ранее, что мы полагаемся на Выключатель роли для доступности. Эта роль требует что атрибут доступности называется Проверено ARIA быть установлены на «True», либо «ложь».
Итак, когда проверено присутствует, Проверено ARIA должно быть «правда», а когда проверено отсутствует, Проверено ARIA должен быть «ложным».
Давайте напишем тест на это!
it('checked attribute is updated', async () => {
const el = await fixture(` `)
expect(el.getAttribute('aria-checked')).to.equal('false')
el.toggleAttribute('checked', true)
expect(el.getAttribute('aria-checked')).to.equal('true')
})
В этом тесте мы сначала убедитесь, что незаменимый тумблер начинается с Проверено ARIA «ложного», указывающего на него доступа к материалам. Затем мы добавляем проверено атрибут и убедитесь, что Проверено ARIA изменился на «правда».
Теперь, чтобы на самом деле выполнить это в коде, требуется, используя классную функцию веб-компонентов: наблюдается атмосферу и AttributeChangedCallback .
наблюдается атмосферуэто просто список атрибутов, которые элемент должен реагировать на его изменение.- И
AttributeChangedCallbackэто функция, которая уволяется, когда любой из перечисленных атрибутов меняется.
class ToggleSwitch extends HTMLElement {
static get observedAttributes() {
return ['checked']
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'checked') {
this.setAttribute('aria-checked', this.checked.toString())
}
}
}
И, наконец, мы захочем убедиться, что первоначальное состояние позаботится о CondentCallback :
class ToggleSwitch extends HTMLElement {
connectedCallback() {
this.setAttribute('aria-checked', this.checked.toString())
}
}
Кодовые функции:
- Атрибуты и свойства Может быть установлен на пользовательских элементах.
- Наблюдательные материалы и AttributeChangedCallback реагировать на изменения в атрибутах.
JavaScript: Нить
А теперь для части колбы, которая на самом деле светится: нить! Как сердце лампочки, он подходит для нити, чтобы представлять сердце нашего компонента, JavaScript API Отказ
Что такое API. ? API. Стенды для интерфейса программирования приложений. Если вы думаете о машине как программе, то его API будет руль, педаль газа и тормозным торможением. Вы не можете напрямую манипулировать тем, что делает двигатель и может сделать это только через эти три доступных веща. Таким образом, API обнажает способы использовать элемент без необходимости знать все свои грязные кишки.
Хотя веб-компонент может быть таким же простым, как просто окрашивающий текст, пользовательские элементы дополнительно полезны для объединения сложных функций в одну диодаду. Например, компонент Toggle Switch должен разрешить кому-то включить его и выключить его, и поэтому действие Click должно быть связано с этим.
Возможно, это неудивительно, так что я нахожу полезным, – думать о тех потенциальных действиях как Общественные функции JavaScript Отказ Еще один способ положить его, если читатель может щелкнуть компонент, чтобы переключить его, то должно быть Переключить () функция доступна, так что Другой код JavaScript Может имитировать действие читателя.
Функции JavaScript разоблачить ключевое поведение элемента и действия.
Для тумблерного переключателя, когда кто-то нажимает на него, элемент должен выходить от ON ON, или от включения. Как обычно, мы начинаем с теста!
describe('toggling on and off', () => {
it('via clicking', async () => {
const el = await fixture(` `)
expect(el.checked).to.be.false
el.click()
expect(el.checked).to.be.true
el.click()
expect(el.checked).to.be.false
})
})
Здесь мы можем использовать Нажмите () Функция для моделирования кого-то нажатия на элемент.
Чтобы сделать этот тестовый пропуск, все, что нам нужно сделать, это слушать событие «Нажмите» и переключить проверено штат. Мы сделаем это в ConnectedCallback С тех пор это хорошее место для обработки инициализации.
class ToggleSwitch extends HTMLElement {
connectedCallback() {
this.addEventListener('click', () => {
this.checked = !this.checked
})
}
}
Выглядит отлично, кроме! Помните нашу ключевую точку:
Ключевым элементом поведения выставлены как Функции JavaScript Отказ
Это означает, что мы должны иметь Переключить () Метод, разоблачение, это ключевой способ, которым могут не только читатели могут взаимодействовать с компонентом, но другой код JavaScript также может.
На самом деле, мы сделаем тест для этого!
describe('toggling on and off', () => {
it('via the api', async () => {
const el = await fixture(` `)
expect(el.checked).to.be.false
el.toggle()
expect(el.checked).to.be.true
el.toggle()
expect(el.checked).to.be.false
})
})
Этот тест чрезвычайно похож на предыдущий тест, с первичной разницей в этом используются публичные функции ( переключатель () ), а не действие пользователя (нажатие).
Делать это позволяет две вещи. Во-первых, мы можем на самом деле упростить слушатель события сверху, чтобы использовать нашу новую функцию:
class ToggleSwitch extends HTMLElement {
toggle = () => {
this.checked = !this.checked
}
connectedCallback() {
this.addEventListener('click', this.toggle)
}
}
Но теперь мы можем сейчас очистить Слушатель событий с DisconnectedCallback крюк!
class ToggleSwitch extends HTMLElement {
disconnectedCallback() {
this.removeEventListener('click', this.toggle)
}
}
Как зеркало для ConnectedCallback , DisconnectedCallback Функция называется каждый раз, когда элемент удален из документа. Это наиболее полезно для очистки слушателей, оно может настроить в другом месте.
Кодовые функции:
- DisconnectedCallback Очищает после элемента, когда он удален из документа.
События: Инертный газ
Так оказывается, есть часть лампы, которую вы не можете видеть, но тем не менее важно для этого работать: инертный газ! Лампа заполнена специальным воздухом, который продлевает срок службы нити.
Продолжая нашу лампочку веб-компонентов, газ представлен Event API , вещи, происходящие под поверхностью, но значимые для других вещей, чтобы реагировать на изменения в нашем компоненте.
событие По сути, по сути, заявляющий о том, что что-то случилось, например, «Эй, кто-то переключил меня!» Выпуская событие, как это, слушатели может реагировать с некоторыми подходящими действиями.
При создании веб-компонента мы должны подумать о том, какие события должны выделять, что другие элементы могут потребоваться реагировать на. На самом деле, это основной механизм, с помощью которого наши Элемент даже будет полезен!
События сообщите ключевые действия или изменения для других элементов для реагирования на.
По сути, наша цель – использовать наш элемент, который будет использоваться следующим образом:
const toggleSwitch = document.querySelector('toggle-switch')
toggleSwitch.addEventListener('toggle-switch:change', (e) => {
// code toggling light/dark mode
})
Думать о нашем Компонент снова, каковы ключевые события, которые мы хотим, чтобы они выделяли? По большей части имеется только один: изменяется ли его состояние от ON ON или наоборот.
Итак, всякий раз, когда проверено Изменения состояния, элемент должен излучать событие!
Чтобы написать тест, мы должны задать три вопроса.
- Что такое событие Имя ?
- Когда происходит ли событие?
- Что Детали должен быть отправлен с мероприятием?
Ответы на эти вопросы будут вписаны в этот хороший шаблон тестирования:
import { oneEvent, fixture, expect } from '@open-wc/testing'
describe('events', () => {
it('turned on', async () => {
const el = await fixture(` `)
setTimeout(() => /* (2) WHEN */)
const { detail } = await oneEvent(el, /* (1) NAME */)
/* (3) ASSERT DETAILS */
})
})
Отвечая на вопросы …
- Имя : Поскольку наше мероприятие представляет собой Изменить В штате мы назовем событие «Toggle-Switch: изменение».
- Когда : Давайте выделяем событие в любое время
проверенодобавляется или удален из элемента. - Детали : События могут нести дополнительную информацию, чтобы слушатели знали оба что случилось и что-то еще, что может быть актуальным. Для нашего одно события, вероятно, важно знать, был ли переключатель переключен или выключен, поэтому мы добавим это к деталям.
Если мы подключим эти вещи в наш тестирующий шаблон, мы получим приличный тест!
import { oneEvent, fixture, expect } from '@open-wc/testing'
describe('events', () => {
it('turned on', async () => {
const el = await fixture(` `)
setTimeout(() => el.checked = true)
const { detail } = await oneEvent(el, 'toggle-switch:change')
expect(detail.checked).to.be.true
})
})
Две важные функции в этом тесте являются Setimeate (Предоставляется JavaScript) и Oneevent (предоставлено Open-WC).
OneeventПросто ждет, чтобы одно событие произошло, и время отказа от неудачи, если событие никогда не возникает.SetimeateДобавляет наш переключатель в список вещей для JavaScript, чтобы сделать в конце концов. Это нужно, потому что если мы не Используйте его, наше мероприятие может потенциально огонь, прежде чем мы даже начали слушать его!
Хорошо, давайте на самом деле излучаем событие сейчас!
Поскольку наше мероприятие наш новый элемент, мы отправляем Пользовательское событие и так как мы хотим сделать это в любое время проверено Изменения, мы выполним отправку с кодом, который реагирует на то, когда этот атрибут изменяется.
class ToggleSwitch extends HTMLElement {
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'checked') {
this.setAttribute('aria-checked', this.checked.toString())
this.dispatchEvent(new CustomEvent('toggle-switch:change', {
detail: {
checked: this.checked
}
}))
}
}
}
Кодовые функции:
- Oneevent Испытания, которые произошло событие.
- Пользовательские события Пусть вы отправляете события, специфичные для вашего компонента.
Стиль: Глобус
Итак, мы сделали Все это кодирование До сих пор, но мы не можем на самом деле Посмотреть Выключатель еще … Давайте, наконец, поставим глобус на нашу лампу, добавив некоторые стиль к нашему элементу!
Если честно, стиль веб-компонентов полностью заслуживает своей собственной статьи, сделанной как интересной, так и осложненной крошечной вещью, называемой Тень Дом Отказ MDN покрывает Используя Shadow DOM В хорошую деталь, поэтому для целей этой статьи мы поговорим об этом, достаточно, чтобы стиль Отказ
Тень Дом Позволяет веб-компонентам, по сути, нести свой собственный персональный документ, скрытый от документа первичного веб-страницы. Это как … Цветы Отказ
Фото Бардия Хашемирада на Бессмысленно
Как садовник, вы не можете сказать цветку, какую форму занять или сколько лепестков, как это определяется собственной ДНК. Вы может Определите, сколько цветов находятся в вашем саду, и, возможно, вы можете повлиять на некоторые из цветов цветов, кормив его окрашенной водой, но за пределы того, что вы не понимаете.
Точно так же тень элемента DOM (цветок) – инкапсулирован Из остальной части документа означает, что документ (садовник) не может напрямую влиять на элементы, определенные в Shadow DOM; Ни один из них не может столкнуться друг с другом.
Это оказывается довольно важным для Потому что у нас сейчас есть конкурирующие проблемы:
- Мы должны использовать Shadow DOM, чтобы дать нашему элементу достойного по умолчанию «Switch Some»
- Но мы также хотим разработчикам настроить его С внешнего компонента соответствовать взглядам своего сайта и чувствовать
Эти конкурирующие проблемы невероятно распространены, и поэтому тень DOM на самом деле не Полностью непроницаемый. Хотя родительский документ никогда не может произвольно настроить вещи в Shadow Dom, есть несколько исключений:
- CSS переменные может принять значения из-за тени DOM.
- Элементы в тени DOM могут быть назначены Названия теневых деталей которые могут быть непосредственно выбраны с CSS.
Эти исключения образуют веб-компонент Стайлинг API конкретно определенные возможности для настройки. И, как правило, как мы должны намеренно решать, какие атрибуты, функции JavaScript и события для выставления, мы также должны выбрать, какие переменные CSS или детали могут быть введены в стили.
Стиль Предварительно доступен через тщательно выбранные переменные CSS и теневые детали.
Ранее я сказал, мы «должны» использовать тень DOM. Почему? В нашем случае мы хотим поддерживать то внутренняя структура элемента, что означает, что он не должен подвергаться воздействию снаружи. Решать, что идет в Shadow DOM или не важно для создания API стиля элемента, но достаточно сложна, чтобы заслужить свою собственную статью. Этот стек переполняет пост Помогил мне понять эту концепцию и ссылки на другие полезные ресурсы.
В течение длительного времени давайте стиль этого веб-компонента!
Чтобы легко настроить переключатель, мы собираемся минимально стиль его. Наш базовый выключатель будет просто квадратом, который движется вперед и назад вдоль такой дорожки:
Во-первых, мы должны приложить тень корня к элементу и создать базовый шаблон для нашего элемента.
const template = document.createElement('template')
template.innerHTML = `
`
class ToggleSwitch extends HTMLElement {
constructor() {
super()
this
.attachShadow({ mode: 'open' })
.appendChild(template.content.cloneNode(true))
}
}
Обратите внимание, мы хотим, чтобы разработчики, используя этот тумблер, чтобы иметь возможность настраивать как скользящую бит, так и дорожку под ним, так что сделать это возможным мы присваиваем Теневые детали каждому элементу. Это позволит пользователям стилить те конкретные компоненты, такие как это:
toggle-switch::part(slider) {
border-radius: 1em;
}
С помощью основной структуры шаблона сделана все, что осталось, добавляет CSS! Все добавленные CSS будут входить в Стиль Тег в шаблоне выше.
Во-первых, давайте дадим элемент какой-то базовый размер.
:host {
display: inline-block;
width: 2em;
height: 1em;
cursor: pointer;
}
span {
box-sizing: border-box;
display: inline-block;
line-height: 1;
}
Вот два интереса:
-
: хозяинСелектор особенный в контексте Shadow Dom. Он в основном означает «стиль вещи , который содержит Shadow DOM», который является сама веб-компонента. В нашем случае это стилиToggle-Switchярлык. -
ПромежутокТолько выбирает охватываний В течение Shadow Dom элемента. Это делает не Все глобально стиль всех пролетов на странице! Это часть силы инкапсуляции.
Далее мы стимулируем трек и слайдер, чтобы выглядеть как наши квадратные примеры:
[part="track"] {
width: 100%;
height: 100%;
background-color: #dddddd;
text-align: left;
}
[part="slider"] {
width: 50%;
height: 100%;
background-color: #777777;
vertical-align: text-top;
}
И за последнюю часть нам нужно стиль, что выглядит компонент, когда он был проверен. Напомним, что проверено атрибут на Тег определяет его состояние включения/выключения. Это может быть выбрано с помощью селектора атрибута, используя : хозяин Действительно
[part="track"], [part="slider"] {
transition: all 256ms;
}
:host([checked]) [part="slider"] {
transform: translateX(100%);
}
Кодовые функции:
- Тень Дом Инкапсулирует структуру, стиль и поведение из общего документа.
- Теневые детали Разрешить внешние CSS настроить определенные внутренние элементы веб-компонента.
- : хозяин Позволяет стимулировать сам веб-компонент из своей тени DOM.
Мы изобрели лампочку!
И с этим мы просто охватывали шесть ключевых аспектов Чтобы построить отличные веб-компоненты! И в процессе мы построили обе лампочку и тумблер!
- Веб-компоненты Создать Новая семантика через пользовательские элементы.
- Доступны Компоненты позволяют несколько методов взаимодействия.
- Атрибуты Поверхность Важное состояние, конфигурация и нюанс смысл.
- Функции JavaScript разоблачить ключевое поведение элемента и действия.
- События сообщите ключевые действия или изменения для других элементов для реагирования на.
- Стиль Предварительно доступен через тщательно выбранные переменные CSS и теневые детали.
Но … это действительно завершено?
Почти! Есть несколько вещей, которые я пропустил, чтобы упростить учебное пособие:
- Доступность: Как мы отметим коммутатор? Можем ли мы интегрировать это с HTML
этикеткаэлемент? - JavaScript: когда кто-то вкладывается в переключатель, могут ли они активировать его, нажав Введите или Пространство ?
- Атрибуты: можно ли тумблер быть
ОтключеноКак и другие элементы управления входным HTML?
Не стесняйтесь попытаться решить эти проблемы самостоятельно! Или посмотрите, как все это работает в моей реализации Элемент на github.
Auroratide/Toggle-Switch
Полный код
const template = document.createElement('template')
template.innerHTML = `
`
export class ToggleSwitch extends HTMLElement {
static elementName = 'toggle-switch'
static get observedAttributes() {
return ['checked']
}
constructor() {
super()
this
.attachShadow({ mode: 'open' })
.appendChild(template.content.cloneNode(true))
}
connectedCallback() {
this.setAttribute('role', 'switch')
this.setAttribute('tabindex', '0')
this.addEventListener('click', this.toggle)
}
disconnectedCallback() {
this.removeEventListener('click', this.toggle)
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'checked') {
this.setAttribute('aria-checked', this.checked.toString())
this.dispatchEvent(new CustomEvent('toggle-switch:change', {
detail: {
checked: this.checked
}
}))
}
}
get checked() {
return this.hasAttribute('checked')
}
set checked(value) {
this.toggleAttribute('checked', value)
}
toggle = () => {
this.checked = !this.checked
}
}
window.customElements.define(ToggleSwitch.elementName, ToggleSwitch)
import { fixture, expect } from '@open-wc/testing'
describe('toggle-switch', () => {
describe('accessibility', () => {
it('default role', async () => {
const el = await fixture(` `)
expect(el.getAttribute('role')).to.equal('switch')
})
it('tabbing', async () => {
const el = await fixture(` `)
expect(el.getAttribute('tabindex')).to.equal('0')
})
})
describe('attributes', () => {
it('checked attribute is updated', async () => {
const el = await fixture(` `)
expect(el.getAttribute('aria-checked')).to.equal('false')
el.toggleAttribute('checked', true)
expect(el.getAttribute('aria-checked')).to.equal('true')
})
})
describe('toggling on and off', () => {
it('via clicking', async () => {
const el = await fixture(` `)
expect(el.checked).to.be.false
el.click()
expect(el.checked).to.be.true
el.click()
expect(el.checked).to.be.false
})
it('via the api', async () => {
const el = await fixture(` `)
expect(el.checked).to.be.false
el.toggle()
expect(el.checked).to.be.true
el.toggle()
expect(el.checked).to.be.false
})
})
describe('events', () => {
it('turned on', async () => {
const el = await fixture(` `)
setTimeout(() => el.checked = true)
const { detail } = await oneEvent(el, 'toggle-switch:change')
expect(detail.checked).to.be.true
})
})
})
- Создание веб-компонентов как профессионал.
- @ Open-WC/тестирование Обеспечивает полезные тестирование помощников для набора нашего компонента на веб-странице.
- @ Веб/тест-бегун Запускает наши тесты в реальном браузере.
- Тестовые приспособления Установите элемент на странице для тестирования.
- ConnectedCallback Инициализирует элемент при вставке на страницу.
- Атрибуты и свойства Может быть установлен на пользовательских элементах.
- Наблюдательные материалы и AttributeChangedCallback реагировать на изменения в атрибутах.
- DisconnectedCallback Очищает после элемента, когда он удален из документа.
- Oneevent Испытания, которые произошло событие.
- Пользовательские события Пусть вы отправляете события, специфичные для вашего компонента.
- Тень Дом Инкапсулирует структуру, стиль и поведение из общего документа.
- Теневые детали Разрешить внешние CSS настроить определенные внутренние элементы веб-компонента.
- : хозяин Позволяет стимулировать сам веб-компонент из своей тени DOM.
Оригинал: “https://dev.to/auroratide/making-a-toggle-switch-into-a-new-html-element-425c”