iT邦幫忙

2025 iThome 鐵人賽

DAY 9
3
Modern Web

原生元件養成計畫:Web Component系列 第 9

DAY 9: Web Component 的屬性 Properties 與 Getter & Setter

  • 分享至 

  • xImage
  •  

我們在前面學習到了監聽 attribute(屬性) 來改變元件的狀態或樣式,而除了 HTML 的 attributes 之外,還有另一種傳遞資料給 component 的方式,就是 properties(也是屬性)

attribute 與 properties


attribute

attribute 因為是設定在 HTML 上,所以他只能以 字串 形式傳遞,雖然可以用 JSON.stringify 轉為字串,但是還需要再轉換回去,所以會比較麻煩。

<cat-spinner size="sm" animation="bounce"> // 直接寫在 html 上的 attribute

properties

properties 則是可以直接透過 JavaScript 存取,但是 properties 不會直接反映在 DOM 上,只能透過 JS 設定,所以他的好處就是可以傳任何的值,不管是陣列或是物件。

spinner.progress = 50; // 直接寫入內容
spinner.status = { progress: 50, stop: false }; // 或是可以直接傳入物件

如果要可以存取 properties ,就要用到 getter & setter 來攔截 properties。

Getter & Setter


其實我在剛學 JS 的時候,一直搞不懂 getter 和 setter,希望以下的說明方式可以讓大家理解:

  • 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>

getter-setter

再加入一個 getter, setter!

前面文章我們有實作了點擊 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>

getter,setter

完善第一個 Web Component cat-spinner


經過前面幾篇文章對於 Web Component 的介紹,相信已經掌握了 Web Components 的基本概念?!
在前面的文章中一直使用了 cat-spinner 來做範例,但是都是片段片段的說明概念。
接下來先需要完善第一個 Web Component: cat-spinner
把核心概念一起走過一遍吧!

實作前,先分析一下這個元件會有的功能:

  1. 可以訂定貓咪顏色:color
  2. 可以設定 spinner 大小: size
  3. 可以設定 spinner 的動畫效果: animation
  4. 可以傳入 loading progress: progress
  5. 可以監聽點擊 overlay 的事件並選擇是否隱藏或顯示 overlay:visible

試試看自己動手做做看吧~


完整程式碼看這裡:

https://codepen.io/unlinun/pen/XWwjgzr

截至今天,我們已經把基礎三大核心、生命週期以及 attributeproperties 的差別釐清,並利用 gettersetter 來攔截 properties 的讀取與設定。應該已經有 Web Component 的感覺了吧?

從可以設定屬性、監聽事件、傳遞資料、控制狀態,到這裡為止,基礎核心其實都具備囉!✧*。٩(ˊᗜˋ*)و✧*。


上一篇
Day 8: Web Component 的事件傳遞 CustomEvent
下一篇
Day 10: Web Component 的插槽 Slot
系列文
原生元件養成計畫:Web Component12
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言