ย
ES6 ๋ช
์ธ์ ๋ณด๋ฉด Web Components๋ผ๋ ๊ฒ์ด ์ ์๋์ด ์๋ค.
์๋ ์ผ์ข
์ ๋ถ๋ฆฌ๋ DOM ์ ๋ง๋ค ์ ์๋๋ก ํ๋๋ฐ, ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
ย
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<my-element>Hello</my-element> <!-- === <h1>Hello</h1> -->
<script>
class MyElement extends HTMLElement {
constructor() {
super();
const template = document.createElement('template');
template.innerHTML = '<h1><slot></slot></h1>';
this.attachShadow({ mode: 'closed' })
.append(template.content.cloneNode(true));
}
}
window.customElements.define(
'my-element',
MyElement,
);
</script>
</body>
</html>
ย
๊ทธ๋ฐ๋ฐ ๋ณด๋ฉด ์๊ฒ ์ง๋ง, ์ ์ฝ๋๋
innerHTML
์ ์ด์ฉํด HTML ์ฝ๋๋ฅผ ์ธ๋ผ์ธ์ผ๋ก ๋ฃ์ด์ค์ผ ํ๋ค๋ ๋ถํธํจ์ด ์๊ธฐ ๋๋ฌธ์...ย
๋ค์๊ณผ ๊ฐ์ด
xhr
์ ์ด์ฉํด ๋ถ๋ฆฌํด์ค ์๋ ์๋ค.ย
class MyElement extends HTMLElement {
constructor() {
super();
_connect();
}
async _connect() {
const rawHtml = await (await fetch(/* html src */)).text();
const template = document.createElement('template');
template.innerHTML = rawHtml;
this.attachShadow({ mode: 'closed' })
.append(template.content.cloneNode(true));
}
}
window.customElements.define(
'my-element',
MyElement,
);
ย
๋ค๋ง ES6์ Class Constructor๋
async
ํ ์ ์๊ธฐ ๋๋ฌธ์์ด์ฉ ์ ์์ด ๋ฉ์๋๋ฅผ ํ๋ ์์ฑํด์ค์ผ ํ๋ค.
ย
๋ฌผ๋ก ๋ค์๊ณผ ๊ฐ์ด
then
์ ์ด์ฉํด์๋ ๊ฐ๋ฅ์ ํ๋ฐย
class MyElement extends HTMLElement {
constructor() {
super();
fetch(/* html src */)
.then(async (resp) => await resp.text())
.then((rawHtml) => {
const template = document.createElement('template');
template.innerHTML = rawHtml;
this.attachShadow({ mode: 'closed' })
.append(template.content.cloneNode(true));
});
}
}
window.customElements.define(
'my-element',
MyElement,
);
ย
์ด๊ฑด ๊ทธ๋ฅ ๊ฐ์ธ์ ์ผ๋ก ๋ง์ ๋ค์ง ์์๋ค. ๊ทธ๋์ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด ์๋ ์๊ฐํด ๋ณด์๊ณ ...
ES6์
import
๊ตฌ๋ฌธ์ด ๋ ์ฌ๋๋ค.ย
import rawHtml from './my-element.html'; // ERROR
class MyElement extends HTMLElement {
constructor() {
super();
const template = document.createElement('template');
template.innerHTML = rawHtml;
this.attachShadow({ mode: 'closed' })
.append(template.content.cloneNode(true));
}
}
ย
๋๋ ์์งํ ๋ ์ค ์์๋ค. ๊ทธ๋ฐ๋ฐ ์ ์ด๋ ํ์ฌ๋ก์๋ ์ค๋ก์ง js ํ์ผ๋ง์ import ํ ์ ์๋ค๊ณ ํ๋ค.
ย
๊ทธ๋์ ๋ด๊ฐ ์๊ฐํ ๋ฐฉ๋ฒ์?
์ด์ฐจํผ ES6์
class
๋ ์ค์ ๋ก๋ ES5์ function
Class Declaration์ ์ถ์ฝํ ๊ฒ์ผ ๋ฟ์ด๋๊น...ย
class Foo { }
console.log(typeof Foo); // "function"
ย
๊ทธ๋์ ๋ค์๊ณผ ๊ฐ์ ๋ชจ๋์ ํ๋ ๊ตฌํํ๋ค.
ย
/**
* raw html data loader
*
* @param {String} src source link
*/
const rawHtmlLoader = async (src) => await (await fetch(src)).text();
export default async (src) => {
// create a template lement
const template = document.createElement('template');
// set contents
template.innerHTML = await rawHtmlLoader(src);
// define custom element class (es5 version for async extends)
function CustomComponent() {
const customComponent = Reflect.construct(HTMLElement, [], CustomComponent);
// attach shadow
customComponent.attachShadow({ mode: 'closed' })
.append(template.content.cloneNode(true));
// return reflected constructor
return customComponent;
}
// set prototype
CustomComponent.prototype = Object.create(HTMLElement.prototype);
// return custom component element
return CustomComponent;
};
ย
์ ์ฝ๋๋ ๊ทธ๋ฅ ES5 ๋ฌธ๋ฒ์ผ๋ก Class๋ฅผ ๊ตฌํํ ๊ฒ์ด๊ณ ,
์ฌ๊ธฐ์ Reflection์ ์ด์ฉํด
HTMLElement
๋ฅผ extends
ํ ์ฝ๋์ด๋ค.ย
์ ์ด๋ ๊ฒ ํ๋? ๋ฐ๋ก
async
๋ฅผ ์ด์ฉํ extends
๋ฅผ ๊ตฌํํ๊ธฐ ์ํด์ ์ด๋ฐ ์ง์ ํ ๊ฒ์ด๋ค.ย
์๋ฌดํผ, ์ด ๋ชจ๋์ ํตํด ๋ค์๊ณผ ๊ฐ์ด html ํ์ฅ์๋ฅผ ๊ฐ์ง
template
์ ๋ฐ๋ก Loadํ ์ ์๋ค.๋ฌผ๋ก ์นํฉ์ด๋ ๋ญ ๊ทธ๋ฐ๊ฑฐ ์์ด Vanilla JS์์ ๋ง์ด๋ค.
ย
import loader from './loader.js';
window.addEventListener('load', async () => {
window.customElements.define(
'my-element',
await loader('/components/my-element.html');
);
});
<!-- /components/my-element.html -->
<h1>
<slot></slot>
</h1>
<!-- ๋ญ ์ด๋ฐ ๊ฒ๋ ๋น์ฐํ ์ฌ์ฉ ๊ฐ๋ฅ -->
<style scoped>
h1 {
font-weight: 100;
}
</style>
ย
๊ฐ์ธ์ ์ผ๋ก ์ด๋ฌํ ๋ฐฉ์์ด ๋ง์์ ๋ค์๋ค. ์กฐ๊ธ ๋ ๊น๋ํ๋ค๊ณ ์๊ฐํ๋ค.
๊ทผ๋ฐ ๋ ๋ณด๋ฉด ๋ฉ๋ฆฌ ๋์์จ ๊ฒ ๊ฐ๊ธฐ๋ ํ๊ณ ... ์๋ฌดํผ ๋ญ ์์ฌ์ด ์๊ฒจ ๊ตฌํํด ๋ณธ ๋ชจ๋.
ย
GitHub์ ์ฝ๋๋ ์ฌ๋ ค๋์๋ค.
์ฐธ๊ณ ๋ก ๋ค์๊ณผ ๊ฐ์ด๋ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
ย
import componentLoader from 'https://raw.githack.com/Gumball12/vanilla-component-loader/main/index.js';
window.addEventListener('load', async () => {
customElements.define(
'my-element',
await componentLoader('/components/my-element.html'),
);
});
ย
ย
+
๋น์ฐํ ์ข ๋ ๋์ ๋ฐฉ๋ฒ์ด ์กด์ฌํ๋ค..
Vanilla JS๋ก MVVM ํ๋ ์์ํฌ๋ฅผ ๊ตฌํํด๋ณด๋ฉฐ ์๊ฒ ๋์๋๋ฐ,
๊ทธ๋ฅ ์๋ก์ด class๋ฅผ ๊ตฌํํ๋ฉด ๋์๋ ๊ฒ...
ย
Loading Comments...