Web Components Getting Started Example Tutorial
Components are the development direction of the front-end. Now popular React and Vue are both component frameworks.
Since Google has mastered the Chrome browser, it has been promoting the browser’s native components, the Web Components API . Compared with third-party frameworks, native components are simple, straightforward and intuitive, without loading any external modules, and the amount of code is small. At present, it is still under development, but it is already available in production environments.
Web Components API contains a lot of content. This article is not a comprehensive tutorial, but a simple demonstration, let everyone see how to use it to develop components.
One, custom elements
The picture below is a user card.
This article demonstrates how to write this card as a Web Components component. Here is the final complete code .
As long as the webpage inserts the following code, the user card will be displayed.
<user-card></user-card>
Such custom HTML tags are called custom elements.
According to the specification, the name of a custom element must include a conjunction line to distinguish it from native HTML elements.
Therefore, it
<user-card>
cannot be written
<usercard>
.
two,
customElements.define()
Custom elements need to use JavaScript to define a class, and all
<user-card>
will be instances of this class.
class UserCard extends HTMLElement { constructor() { super(); } }
In the above code, it
UserCard
is the class of the custom element.
Note that the parent of this class is
HTMLElement
, and therefore inherits the characteristics of HTML elements.
Next, use the browser’s native
customElements.define()
method to tell the browser that the
<user-card>
element is associated with this class.
window.customElements.define('user-card', UserCard);
Three, the content of the custom element
The custom element
<user-card>
is currently empty. The content of this element is given in the class below.
class UserCard extends HTMLElement { constructor() { super(); var image = document.createElement('img'); image.src = 'https://semantic-ui.com/images/avatar2/large/kristy.png'; image.classList.add('image'); var container = document.createElement('div'); container.classList.add('container'); var name = document.createElement('p'); name.classList.add('name'); name.innerText = 'User Name'; var email = document.createElement('p'); email.classList.add('email'); email.innerText = 'yourmail@some-email.com'; var button = document.createElement('button'); button.classList.add('button'); button.innerText = 'Follow'; container.append(name, email, button); this.append(image, container); } }
The last line of
this.append()
the
above code
this
represents an instance of a custom element.
After completing this step, the DOM structure inside the custom element has been generated.
Fourth, the
<template>
label
Using JavaScript to write the DOM structure of the previous section is very troublesome. The Web Components API provides
<template>
tags, in which HTML can be used to define the DOM.
<template id="userCardTemplate"> <img src="https://semantic-ui.com/images/avatar2/large/kristy.png" class="image"> <div class="container"> <p class="name">User Name</p> <p class="email">yourmail@some-email.com</p> <button class="button">Follow</button> </div> </template>
Then, rewrite the class of the custom element and load it for the custom element
<template>
.
class UserCard extends HTMLElement { constructor() { super(); var templateElem = document.getElementById('userCardTemplate'); var content = templateElem.content.cloneNode(true); this.appendChild(content); } }
In the above code,
<template>
after
obtaining the
node, all its child elements are cloned. This is because there may be multiple instances of custom elements. This template is also reserved for other instances, so its child elements cannot be moved directly.
Up to this step, the complete code is as follows.
<body> <user-card></user-card> <template>...</template> <script> class UserCard extends HTMLElement { constructor() { super(); var templateElem = document.getElementById('userCardTemplate'); var content = templateElem.content.cloneNode(true); this.appendChild(content); } } window.customElements.define('user-card', UserCard); </script> </body>
Five, add style
The custom element does not have a style yet, you can assign a global style to it, such as the following.
user-card { /* ... */ }
However, the style of the component should be encapsulated with the code, which only takes effect on the custom element, and does not affect the external global style.
So, you can write the style in
<template>
it.
<template id="userCardTemplate"> <style> :host { display: flex; align-items: center; width: 450px; height: 180px; background-color: #d4d4d4; border: 1px solid #d5d5d5; box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1); border-radius: 3px; overflow: hidden; padding: 10px; box-sizing: border-box; font-family: 'Poppins', sans-serif; } .image { flex: 0 0 auto; width: 160px; height: 160px; vertical-align: middle; border-radius: 5px; } .container { box-sizing: border-box; padding: 20px; height: 160px; } .container > .name { font-size: 20px; font-weight: 600; line-height: 1; margin: 0; margin-bottom: 5px; } .container > .email { font-size: 12px; opacity: 0.75; line-height: 1; margin: 0; margin-bottom: 15px; } .container > .button { padding: 10px 25px; font-size: 12px; border-radius: 5px; text-transform: uppercase; } </style> <img src="https://semantic-ui.com/images/avatar2/large/kristy.png" class="image"> <div class="container"> <p class="name">User Name</p> <p class="email">yourmail@some-email.com</p> <button class="button">Follow</button> </div> </template>
In the above code,
<template>
the
:host
pseudo-class
in the
style
refers to the custom element itself.
Six, the parameters of custom elements
<user-card>
The content is now
<template>
set in it. For the convenience of use, change it to a parameter.
<user-card image="https://semantic-ui.com/images/avatar2/large/kristy.png" name="User Name" email="yourmail@some-email.com" ></user-card>
<template>
The code is also modified accordingly.
<template id="userCardTemplate"> <style>...</style> <img class="image"> <div class="container"> <p class="name"></p> <p class="email"></p> <button class="button">Follow John</button> </div> </template>
Finally, change the code of the class and add the parameters to the custom element.
class UserCard extends HTMLElement { constructor() { super(); var templateElem = document.getElementById('userCardTemplate'); var content = templateElem.content.cloneNode(true); content.querySelector('img').setAttribute('src', this.getAttribute('image')); content.querySelector('.container>.name').innerText = this.getAttribute('name'); content.querySelector('.container>.email').innerText = this.getAttribute('email'); this.appendChild(content); } } window.customElements.define('user-card', UserCard);
DOM 、 Shadow DOM
We don’t want users to be able to see
<user-card>
the internal code. Web Component allows the internal code to be hidden. This is called Shadow DOM, that is, this part of the DOM is isolated from the external DOM by default, and any internal code cannot affect the external.
The
this.attachShadow()
method of
customizing elements
opens Shadow DOM, see the code below for details.
class UserCard extends HTMLElement { constructor() { super(); var shadow = this.attachShadow( { mode: 'closed' } ); var templateElem = document.getElementById('userCardTemplate'); var content = templateElem.content.cloneNode(true); content.querySelector('img').setAttribute('src', this.getAttribute('image')); content.querySelector('.container>.name').innerText = this.getAttribute('name'); content.querySelector('.container>.email').innerText = this.getAttribute('email'); shadow.appendChild(content); } } window.customElements.define('user-card', UserCard);
In the above code,
this.attachShadow()
the parameters of the method
{ mode: 'closed' }
indicate that the Shadow DOM is closed and does not allow external access.
At this point, the Web Component component is complete, and the complete code can be accessed here . As you can see, the whole process is still very simple, unlike third-party frameworks that have complex APIs.
Eight, component expansion
On the basis of the previous, the components can be extended.
(1) Interact with users
The user card is a static component. If you want to interact with the user, it is very simple to listen to various events in the class.
this.$button = shadow.querySelector('button'); this.$button.addEventListener('click', () => { // do something });
(2) Package of components
In the above example,
<template>
put together with the webpage code, you can actually
<template>
inject the
script
into the webpage.
In this way, the JavaScript script
<template>
can be packaged into a JS file and become an independent component file.
As long as the web page loads this script, the
<user-card>
component
can be used
.
I won’t expand here. For more advanced usage of Web Components, you can continue to study the following two articles.
Nine, reference link
- The anatomy of Web Components , Uday Hiwarale
(over)