我們在前面學習到了監聽 attribute(屬性)
來改變元件的狀態或樣式,而除了 HTML 的 attributes 之外,還有另一種傳遞資料給 component 的方式,就是 properties(也是屬性)
。
attribute 因為是設定在 HTML 上,所以他只能以 字串
形式傳遞,雖然可以用 JSON.stringify
轉為字串,但是還需要再轉換回去,所以會比較麻煩。
<cat-spinner size="sm" animation="bounce"> // 直接寫在 html 上的 attribute
properties 則是可以直接透過 JavaScript 存取,但是 properties 不會直接反映在 DOM 上,只能透過 JS 設定,所以他的好處就是可以傳任何的值,不管是陣列或是物件。
spinner.progress = 50; // 直接寫入內容
spinner.status = { progress: 50, stop: false }; // 或是可以直接傳入物件
如果要可以存取 properties ,就要用到
getter & setter
來攔截 properties。
其實我在剛學 JS 的時候,一直搞不懂 getter 和 setter,希望以下的說明方式可以讓大家理解:
讀取
元件內的屬性時,會先經過這個方法,然後再回傳值。設定
元件內的屬性時,會先經過這個方法,然後再決定如何處理這個值。如果我們想加入一個 progress 讓外部可以設定數值,內部也可以讀取的話,可以這樣做:
加入 progress 屬性的 getter 與 setter
spinner.js
// 補充: 加入 `_` 代表這個變數是內部用的,不建議在外部直接存取到外部設定的參數
// Getter - 外部要讀取元件內的屬性時走這條路
get progress() {
return this._progress;
}
// Setter - 外部設定屬性觸發這條路的方法
set progress(value) {
this._progress = Number(value) || 0;
this.shadowRoot.querySelector('#progress').textContent = this._progress;
}
在外部取得內部屬性值並傳值給元件
index.html
<script>
const spinner = document.querySelector('cat-spinner');
let progress = 0;
const timer = setInterval(() => {
progress += 5; // 每次增加 5
if (progress > 100) {
progress = 100;
}
spinner.progress = progress; // 更新 Web Component 的 setter
if (progress >= 100) {
clearInterval(timer);
}
}, 1000);
spinner.addEventListener('overlay-click', () => {
spinner.visible = !spinner.visible;
});
</script>
前面文章我們有實作了點擊 overlay 要觸發的 custom event,而當時外部是直接使用 spinner.remove
將 spinner 直接從 DOM 中移除。
但其實在這篇文章中,希望可以利用 getter 與 setter 讓外部可以控制 spinner 的顯示與隱藏,而不要直接移除整個 DOM 元素。
spinner.js
// 首先在 spinnerTemplate.innerHTML 加入 style
spinnerTemplate.innerHTML = `
<style>
.hidden {
display: none;
}
</style>
// ... 以下略過
`
constructor() {
// ... 以上為寫入 shadowDOM,略..
this._overlay = this.shadowRoot.querySelector('.overlay');
}
// Getter - 外部讀取時,提供目前 _overlay 是否隱藏
get visible() {
return !this._overlay.classList.contains('hidden');
}
// Setter - 外部設定時,內部可以拿到傳入的值
set visible(state) {
this._overlay.classList.toggle('hidden', !state);
}
index.html
外部控制透過元件的自訂事件獲取事件,並且寫入 visible 參數。
<script>
spinner.addEventListener('overlay-click', () => {
if (window.confirm('確定不等小貓?')) {
spinner.visible = !spinner.visible;
}
});
</script>
cat-spinner
經過前面幾篇文章對於 Web Component 的介紹,相信已經掌握了 Web Components 的基本概念?!
在前面的文章中一直使用了 cat-spinner
來做範例,但是都是片段片段的說明概念。
接下來先需要完善第一個 Web Component: cat-spinner
。
把核心概念一起走過一遍吧!
實作前,先分析一下這個元件會有的功能:
color
size
animation
progress
visible
試試看自己動手做做看吧~
https://codepen.io/unlinun/pen/XWwjgzr
截至今天,我們已經把基礎三大核心、生命週期以及 attribute
和 properties
的差別釐清,並利用 getter
與 setter
來攔截 properties 的讀取與設定。應該已經有 Web Component 的感覺了吧?
從可以設定屬性、監聽事件、傳遞資料、控制狀態,到這裡為止,基礎核心其實都具備囉!✧*。٩(ˊᗜˋ*)و✧*。