Создание своего элемента HTML

Последнее обновление: 05.03.2021

По умолчанию HTML предоставляет ряд встроенных элементов, из которых мы можем составить структуру веб-страницы. Однако мы не ограничены встроенными html-элементами и можем сами создать и использовать свои элементы html.

В JavaScript HTML-элемент представлен интерфейсом HTMLElement. Соответственно, реализуя данный интерфейс в JavaScript, мы можем создать свои классы, которые будут представлять элементы html, и потом их использовать. Что-то наподобие следующего:

<!DOCTYPE html>
<html>
<head>
<title>METANIT.COM</title>
<meta charset="utf-8">
</head>
<body>
<hello-metanit></hello-metanit>
</script>
</body>
</html>

В данном случае в коде странице определен элемент <hello-metanit>, и в реальности такого элемента конечно же не существует. Но сейчас мы его создадим.

Итак, чтобы определить класс, который будет представлять html-элемент, нам достаточно создать класс, который реализует интерфейс HTMLElement:

class HelloMetanit extends HTMLElement {

}

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

customElements.define(name, constructor, options);

Она принимает три параметра:

  • name: имя кастомного элемента html, который будет представлять класс JavaScript. Важно: имя должно содержать дефис.

  • constructor: конструктор (по сути класс JavaScript), который представляет кастомный элемент html.

  • options: необязательный параметр - объект, который настраивает кастомный html-элемент. В настоящий момент он поддерживает один параметр - extends. Он определяет название встроенного html-элемента, который применяется для создания кастомного элемента html.

Например, в нашем случае мы могли бы вызвать эту функцию так:

customElements.define("hello-metanit", HelloMetanit);

То есть в общем это будет выглядеть следующим образом:

<!DOCTYPE html>
<html>
<head>
<title>METANIT.COM</title>
<meta charset="utf-8">
</head>
<body>

<hello-metanit></hello-metanit>

<script>
class HelloMetanit extends HTMLElement {
	
}
customElements.define("hello-metanit", HelloMetanit);
</script>
</body>
</html>

Но пока кастомный элемент "hello-metanit" ничего не делает. Добавим ему какую-нибудь примитивную задачу. Пусть он выводит некоторое приветствие.

Как правило, классы кастомных элементов применяют конструктор. Причем в самом начале конструктора должен идти вызов функции super(), который гарантирует, что наш класс унаследовал все методы, атрибуты и свойства интерфейса HTMlElement.

class HelloMetanit extends HTMLElement {
	constructor() {
        super();
    }
}

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

<!DOCTYPE html>
<html>
<head>
<title>METANIT.COM</title>
<meta charset="utf-8">
</head>
<body>

<hello-metanit></hello-metanit>

<script>
class HelloMetanit extends HTMLElement {
	constructor() {
        super();
		
		let welcome = "Доброе утро";
		const hour = new Date().getHours();
		if (hour > 17) {
			welcome = "Добрый вечер";
		} else if (hour > 12) {
			welcome = "Добрый день";
		}
		
		this.innerText= welcome;
		// либо так
		// this.textContent = welcome;
    }
}

customElements.define("hello-metanit", HelloMetanit);
</script>
</body>
</html>

В конструкторе мы получаем текущее время и в зависимости от текущего часа определяем текст приветствия. Поскольку наш класс применяет интерфейс HTMLElement, то соответственно мы можем в нем использовать стандартные для html-элементов свойства. В частности, в данном случае для установки текста элемента применяется свойство innerText (также можно было бы использовать свойство textContent).

Создание html-элемента и HTMLElement

Добавление методов

Как и в обычных классах, мы можем определять в классах элементов методы и затем вызывать их. Например, определим простейший метод, который возвращает текущее время:

<!DOCTYPE html>
<html>
<head>
<title>METANIT.COM</title>
<meta charset="utf-8">
</head>
<body>

<hello-metanit id="hello"></hello-metanit>
<script>
class HelloMetanit extends HTMLElement {
	
	constructor() {
        super();
		
		let welcome = "Доброе утро";
		const hour = new Date().getHours();
		if (hour > 17) {
			welcome = "Добрый вечер";
		} else if (hour > 12) {
			welcome = "Добрый день";
		}
		this.style="cursor:pointer;"
		this.innerText= welcome;
    }
	
	showTime(){
		console.log(new Date().toTimeString());
	}
}

customElements.define("hello-metanit", HelloMetanit);

// получаем элемент
const hello = document.getElementById("hello");
// по нажатию вызываем его метод showTime
hello.addEventListener("click", ()=> hello.showTime());
</script>
</body>
</html>

Для примера в классе элемента определен метод showTime, который просто выводит на консоль текущее время. В коде javascript мы получаем по id данный элемент, прикрепляем к нему обработчик нажатия, в котором вызываем вышеопределенный метод showTime(). В итоге по нажатию в консоли мы увидим текущее время:

Создание html-элемента и HTMLElement и customElements.define

События жизненного цикла

Кастомный элемент html имеет свой жизненный цикл, который описывается следующими методами:

  • connectedCallback: вызывается каждый раз, когда кастомный элемент html добавляется в DOM.

  • disconnectedCallback: вызывается каждый раз, когда кастомный элемент html удаляется из DOM.

  • adoptedCallback: вызывается каждый раз, когда кастомный элемент html перемещается в новый элемент.

  • attributeChangedCallback: вызывается при каждом изменении (добавлении, изменении значения или удаления) атрибута кастомного элемента html.

Например, применим метод connectedCallback():

<!DOCTYPE html>
<html>
<head>
<title>METANIT.COM</title>
<meta charset="utf-8">
</head>
<body>

<hello-metanit id="hello"></hello-metanit>
<script>
class HelloMetanit extends HTMLElement {
	
	constructor() {
        super();
		
		let welcome = "Доброе утро";
		const hour = new Date().getHours();
		if (hour > 17) {
			welcome = "Добрый вечер";
		} else if (hour > 12) {
			welcome = "Добрый день";
		}
		this.style.cursor="pointer"
		this.innerText= welcome;
    }
	connectedCallback() {
	  this.style.color = "red";
	}
	showTime(){
		console.log(new Date().toTimeString());
	}
}

customElements.define("hello-metanit", HelloMetanit);
</script>
</body>
</html>

В данном случае в методе connectedCallback() просто устанавливаем цвет шрифта - в данном случае красный цвет:

this.style.color = "red";

Добавление атрибутов

Также мы можем определить у элемента свои атрибуты и затем использовать их. Например, выше при добавлении элемента на страницу у него устанавливается красный цвет текста. Зададим установку цвета с помощью атрибута:

<!DOCTYPE html>
<html>
<head>
<title>METANIT.COM</title>
<meta charset="utf-8">
</head>
<body>

<hello-metanit hellocolor="#2980b9"></hello-metanit>
<br/>
<hello-metanit></hello-metanit>
<script>
class HelloMetanit extends HTMLElement {
	
	constructor() {
        super();
		
		let welcome = "Доброе утро";
		const hour = new Date().getHours();
		if (hour > 17) {
			welcome = "Добрый вечер";
		} else if (hour > 12) {
			welcome = "Добрый день";
		}
		this.style.cursor="pointer"
		this.innerText= welcome;
    }
	connectedCallback() {
		this.style.color = "red";
		if (this.hasAttribute("hellocolor")) {
            this.style.color = this.getAttribute("hellocolor");
		}
	}
	showTime(){
		console.log(new Date().toTimeString());
	}
}

customElements.define("hello-metanit", HelloMetanit);
</script>
</body>
</html>

В данном случае элемент принимает атрибут hellocolor, который задает цвет текста элемента. Если этот атрибут определен, то по нему устанавливаем цвет текста. Если не определен, то применяется цвет по умолчанию - красный:

this.style.color = "red";
if (this.hasAttribute("hellocolor")) {
	this.style.color = this.getAttribute("hellocolor");
}
атрибуты html-элемента и HTMLElement и customElements.define и connectedCallback

Стилизация CSS

Стилизация элемента через CSS производится также, как и стилизация любого другого элемента:

<!DOCTYPE html>
<html>
<head>
<title>METANIT.COM</title>
<meta charset="utf-8">
<style>
hello-metanit{
	font-family: Verdana;
	font-size:22px;
}
</style>
</head>
<body>
<hello-metanit hellocolor="#2980b9"></hello-metanit>
<script>
class HelloMetanit extends HTMLElement {
	
	constructor() {
        super();
		
		let welcome = "Доброе утро";
		const hour = new Date().getHours();
		if (hour > 17) {
			welcome = "Добрый вечер";
		} else if (hour > 12) {
			welcome = "Добрый день";
		}
		this.style.cursor="pointer"
		this.innerText= welcome;
    }
	connectedCallback() {
		this.style.color = "red";
		if (this.hasAttribute("hellocolor")) {
            this.style.color = this.getAttribute("hellocolor");
		}
	}
	showTime(){
		console.log(new Date().toTimeString());
	}
}

customElements.define("hello-metanit", HelloMetanit);
</script>
</body>
</html>
Стилизация CSS для html-элемента и HTMLElement и customElements.define и connectedCallback
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850