內容

內容是一種讓資料可供整個元件子樹使用的方法,而無需手動將屬性繫結到每個元件。 資料是「上下文」可用的,因此,資料提供者和資料消費者之間的祖先元素甚至都不知道它的存在。

Lit 的內容實作可在 @lit/context 套件中取得

內容適用於需要由各種且大量元件取用的資料,例如應用程式的資料儲存、目前使用者、UI 主題,或當資料繫結不是選項時,例如當元素需要將資料提供給其 light DOM 子系時。

內容與 React 的 Context 或 Angular 的依賴注入系統非常相似,但有一些重要的差異,使內容適用於 DOM 的動態本質,並實現跨不同 Web 元件函式庫、框架和純 JavaScript 的互通性。

使用內容涉及 *內容物件*(有時稱為鍵)、*提供者* 和 *消費者*,它們使用內容物件進行通訊。

內容定義 (logger-context.ts)

提供者

消費者

Lit 的內容基於 W3C 的 內容社群協定,由 Web 元件社群小組制定。

此協定可讓元素(甚至非元素程式碼)之間實現互通性,而與它們的建構方式無關。 透過內容協定,基於 Lit 的元素可以將資料提供給未使用 Lit 建構的消費者,反之亦然。

內容協定基於 DOM 事件。 消費者會觸發一個攜帶其所需內容鍵的 context-request 事件,且其上方的任何元素都可以監聽 context-request 事件並為該內容鍵提供資料。

@lit/context 實作了此基於事件的協定,並透過一些響應式控制器和裝飾器使其可用。

內容由內容物件內容鍵識別。 它們是物件,代表要由內容物件識別共用的一些潛在資料。 您可以將它們視為類似於 Map 鍵。

提供者通常是元素(但可以是任何事件處理程式碼),它們為特定的內容鍵提供資料。

消費者會請求特定內容鍵的資料。

當消費者請求內容的資料時,它可以告知提供者它想要訂閱內容的變更。 如果提供者有新資料,則會通知消費者,且可以自動更新。

每次使用內容都必須有一個內容物件來協調資料請求。 此內容物件代表所提供資料的識別和類型。

內容物件是使用 createContext() 函式建立的

建議將內容物件放在它們自己的模組中,以便它們可以獨立於特定的提供者和消費者匯入。

createContext() 接受任何值並直接傳回。 在 TypeScript 中,該值會轉換為類型化的 Context 物件,該物件會隨之攜帶內容的類型。

如果發生像這樣的錯誤

TypeScript 會警告類型 string 無法指派給類型 Logger。 請注意,此檢查目前僅適用於公開欄位。

提供者會使用內容物件來將內容請求事件與值進行比對。 內容會以嚴格相等 (===) 進行比較,因此,只有在其內容鍵等於請求的內容鍵時,提供者才會處理內容請求。

這表示有兩種主要方法可以建立內容物件

  1. 使用全域唯一的值,例如物件 ({}) 或符號 (Symbol())
  2. 使用非全域唯一的值,以便在嚴格相等下可以相等,例如字串 ('logger') 或全域符號 (Symbol.for('logger'))。

如果您希望兩個個別的 createContext() 呼叫參照相同的內容,則請使用在嚴格相等下會相等的鍵,例如字串

但請注意,您應用程式中的兩個模組可以使用相同的內容鍵來參照不同的物件。 若要避免意外衝突,您可能會想要使用相對唯一的字串,例如 'console-logger' 而不是 'logger'

通常最好使用全域唯一的內容物件。 符號是執行此操作的最簡單方法之一。

@lit/context 中,有兩種方法可以提供內容值:ContextProvider 控制器和 @provide() 裝飾器。

如果您正在使用裝飾器,則 @provide() 裝飾器是提供值最簡單的方式。 它會為您建立 ContextProvider 控制器。

使用 @provide() 裝飾屬性並給予它內容鍵

您也可以使用 @property()@state() 使屬性也成為響應式屬性,以便設定它也會更新提供者元素以及內容消費者。

內容屬性通常旨在設為私有。 您可以使用 @state() 使私有屬性成為響應式屬性

將內容屬性設為公開,可讓元素將公開欄位提供給其子樹

ContextProvider 是一個響應式控制器,可為您管理 context-request 事件處理常式。

ContextProvider 可以在建構函式中採用初始值作為選項

或者您可以呼叫 setValue()

如果您正在使用裝飾器,則 @consume() 裝飾器是取用值最簡單的方式。 它會為您建立 ContextConsumer 控制器。

使用 @consume() 裝飾屬性並給予它內容鍵

當此元素連接到文件時,它會自動觸發 context-request 事件、取得提供的值、將其指派給屬性,並觸發元素的更新。

ContextConsumer 是一個響應式控制器,可為您管理 context-request 事件的發送。 當提供新值時,控制器會導致主機元素更新。 然後,可以在控制器的 .value 屬性中找到提供的值。

消費者可以訂閱內容值,以便如果提供者有新值,它可以將其提供給所有已訂閱的消費者,從而導致它們更新。

您可以使用 @consume() 裝飾器進行訂閱

以及 ContextConsumer 控制器

最常見的內容使用案例涉及全域頁面的資料,並且可能僅在整個頁面的元件中零星需要。 如果沒有內容,則大多數或所有元件可能都需要接受和傳播資料的響應式屬性。

應用程式全域服務(例如記錄器、分析、資料儲存)可以由內容提供。 相較於從通用模組匯入,內容的優點是內容提供的後期耦合和樹狀範圍。 測試可以輕鬆提供模擬服務,或者可以為頁面的不同部分提供不同的服務執行個體。

主題是一組樣式,適用於整個頁面或頁面內的整個子樹 - 正好是 context 提供的那種資料範圍。

建立主題系統的一種方法是定義一個 Theme 類型,讓容器可以提供該類型,其中包含已命名的樣式。想要套用主題的元素可以取用主題物件,並透過名稱查詢樣式。自訂主題反應式控制器可以包裝 ContextProvider 和 ContextConsumer,以減少重複程式碼。

Context 可以用來將資料從父元素傳遞到其輕量 DOM 子元素。由於父元素通常不會建立輕量 DOM 子元素,因此它無法利用基於樣板的資料繫結將資料傳遞給它們,但它可以監聽並回應 context-request 事件。

例如,考慮一個具有不同語言模式外掛程式的程式碼編輯器元素。您可以使用 context 建立一個純 HTML 系統來新增功能

在這種情況下,<code-editor> 將提供一個 API,透過 context 新增語言模式,而外掛程式元素將取用該 API 並將自身新增到編輯器中。

連結到「資料格式器、連結產生器等」

有時,可重複使用的元件會需要以應用程式特定的方式格式化資料或 URL。例如,一個文件檢視器會呈現另一個項目的連結。該元件不會知道應用程式的 URL 空間。

在這些情況下,該元件可以依賴 context 提供的函式,該函式會將應用程式特定的格式套用至資料或連結。

這些 API 文件在產生 API 文件之前是摘要。

建立一個具型別的 Context 物件。

匯入:

簽章:

Context 是以嚴格相等的方式進行比較。

如果您希望兩個獨立的 createContext() 呼叫參照相同的 context,則請使用在嚴格相等條件下會相等的鍵,例如 Symbol.for() 的字串。

如果您希望 context 是唯一的,以確保它不會與其他 context 衝突,請使用在嚴格相等條件下唯一的鍵,例如 Symbol() 或物件。

ValueType 類型參數是此 context 可以提供的值的類型。它用於在其他 context API 中提供準確的類型。

一個屬性裝飾器,將 ContextProvider 控制器新增到元件,使其回應來自其子消費者端的任何 context-request 事件。

匯入:

簽章:

一個屬性裝飾器,將 ContextConsumer 控制器新增到元件,它將透過 Context 協定取得屬性的值。

匯入:

簽章:

預設情況下,subscribefalse。將其設定為 true 以訂閱對 context 提供的值的更新。

一個 ReactiveController,透過監聽 context-request 事件,將 context 提供者行為新增到自訂元素。

匯入:

建構函式:

成員

  • setValue(v: T, force = false): void

    設定提供的值,並在值變更時通知任何訂閱的消費者新值。即使值沒有變更,force 也會導致通知,如果物件有深層屬性變更,這可能會很有用。

一個 ReactiveController,透過分派 context-request 事件,將 context 消費行為新增到自訂元素。

匯入:

建構函式:

成員

  • value: ContextType<C>

    context 的目前值。

當主機元素連接到文件時,它會發出一個 context-request 事件,其中包含其 context 鍵。當 context 請求獲得滿足時,控制器會叫用回呼(如果存在),並觸發主機更新,以便它可以回應新值。

當主機元素斷開連接時,它也會呼叫提供者提供的 dispose 方法。

ContextRoot 可用於收集未滿足的 context 請求,並在新的提供者提供符合的 context 鍵時重新分派它們。這允許在消費者之後將提供者新增到 DOM 樹狀結構,或進行升級。

匯入:

建構函式:

成員

  • attach(element: HTMLElement): void

    將 ContextRoot 連接到此元素,並開始監聽 context-request 事件。

  • detach(element: HTMLElement): void

    從此元素分離 ContextRoot,並停止監聽 context-request 事件。

消費者發出的事件,用於請求 context 值。此事件的 API 和行為由Context 協定指定。

匯入:

context-request 會冒泡且是複合的。

成員

  • readonly context: C

    此事件正在請求值的 context 物件

  • readonly callback: ContextCallback<ContextType<C>>

    用來提供 context 值的函式

  • readonly subscribe?: boolean

    消費者是否要訂閱新的 context 值

由 context 請求者提供的回呼,並使用滿足請求的值呼叫。

當請求的值變更時,context 提供者可以多次呼叫此回呼。

匯入:

簽章: