類別

周邊動態/Related Project Update

置信度

Announcement

起始時間

2019-01-08

內容

Web Components 作為官方的組件化方案,由於各種實際操作上的問題飽受詬病,其中一點就是無法自定義表單控制項,仍然只能靠 <input> 或者 <textarea> 元素來組建表單內容而無法自定義同類型的元素(除非不依賴 form 自有的 submit 實現)。

新的 Form Participation API 為自定義表單控制項元素提供了可能性,該提案引入了兩套 API:

  • Event-based participation
  • Form-associated Custom Element

前者已經進入 HTML 規範,而後者仍然處在 Review 階段中,預計能在不遠的將來合併。

對於 Event-based participation 的方式,<form> 在提交階段會觸發 formdata 事件,其事件對象的 formData 屬性即為當前的 FormData。在該事件的處理函數中,可以對其進行修改,從而改變表單的提交內容。形如:

class ShoppingCartApp {
constructor() {
document.querySelector(#cart-form).addEventListener(formdata, this.onFormData.bind(this))
// or el.onformdata = ...
}

onFormData(event) {
event.formData.append(customer-id, this.customerId)
event.formData.append(affiliate-code, this.affiliateCode)
}
}
}

雖然能夠擴充欄位,但 Event-based participation 並沒有將該組件標記為表單控制項,而是一個通用的預處理過程,所以也能夠用於添加欄位以外的其它操作,但一般只用於簡單場景。

而另一種方案 Form-associated Custom Element 會確實將某個 Custom Element 標記為表單控制項,通過名為 formAssociated 的靜態屬性。而後能夠在構造函數中訪問繼承到的 attachInternals() 方法:

class MyControl extends HTMLElement {
static get formAssociated() { return true; }

constructor() {
super();
this.internals = this.attachInternals()
}
}

attachInternals 的返回值是一個 ElementInternals 對象,其結構如下:

interface ElementInternals {
setFormValue(value: FormDataEntryValue, entrySource?: FormData): void

readonly form?: HTMLFormElement

setValidity(flags: ValidityStateFlags, message?: string): void
readonly willValidate: boolean
readonly validity: ValidityState
readonly validationMessage: string
checkValidity(): boolean
reportValidity(): boolean

readonly labels: NodeList
}

該對象用於獲取表單狀態以及進行表單操作。除此之外,標記為 formAssociated 的元素還將獲得額外的生命周期:

  • formAssociatedCallback(form?: HTMLFormElement):與 <form> 關聯後調用;
  • disabledStateChangedCallback(disabled: boolean):所在 <fieldset> 啟用狀態變化時調用;
  • formResetCallback():表單重置時調用;
  • restoreValueCallback(v: FormDataEntryValue, mode: restore | autocomplete):非用戶填充時調用;

而後通過 ElementInternals 中的內容以及相應的生命周期與表單進行實時交互。

相關鏈接

  • Form Participation API 的 Explainer:docs.google.com/documen
  • Event-based form participation API 的 PR:Event-based form participation by tkent-google · Pull Request #4239 · whatwg/html
  • Form-associated Custom Element API 的 PR:Custom elements: Add element.attachInternals() and ElementInternals interface by tkent-google · Pull Request #4324 · whatwg/html
  • Web Components 中的相關討論:Need callback for form submit data · Issue #187 · w3c/webcomponents
  • Design Review 的 issue:Form Participation API · Issue #305 · w3ctag/design-reviews

推薦閱讀:

相关文章