查看原始程式碼 Phoenix.LiveView.Engine (Phoenix LiveView v0.20.17)
追蹤變動的 EEx
範本引擎。
Phoenix.LiveView.TagEngine
常會用這個,它還會加上 HTML 驗證。在以下的文件中,我們將說明它的內部運作方式。使用者文件請參閱 Phoenix.LiveView
。
Phoenix.LiveView.Rendered
每當您呈現即時範本,它會傳回一個 Phoenix.LiveView.Rendered
結構。此結構有三個欄位::static
、:dynamic
和 :fingerprint
。
:static
欄位是一個字串文字清單。藉此,Elixir 編譯器可以最佳化此清單,並避免在每次呈現時配置其字串。
:dynamic
欄位包含一個接收布林值引數的函數 (請參閱下列「追蹤變動」),並傳回一個動態內容清單。清單中的每個元素可能是下列其中之一
- Iodata - 這是動態內容
- nil - 動態內容沒有變更
- 另一個
Phoenix.LiveView.Rendered
結構,請參閱下列「巢狀結構和指紋」 - 一個
Phoenix.LiveView.Comprehension
結構,請參閱下列「理解」 - 一個
Phoenix.LiveView.Component
結構,請參閱下列「元件」
當您呈現即時範本時,您可以交替使用靜態欄位和動態欄位,將呈現結構轉換為 iodata,一律從靜態項目開始,後接一個動態項目。最後一個項目也會是靜態的。因此,下列結構
%Phoenix.LiveView.Rendered{
static: ["foo", "bar", "baz"],
dynamic: fn track_changes? -> ["left", "right"] end
}
會產生下列內容,並透過 iodata 傳送
["foo", "left", "bar", "right", "baz"]
這也是當您使用 Phoenix.HTML.Safe.to_iodata/1
和 Phoenix.LiveView.Rendered
結構時,它傳回的結果。
當然,即時範本的好處就在於,您並不需要每次都傳送靜態和動態區段。所以,讓我們談談追蹤變動吧。
追蹤變動
預設情況下,即時範本不會追蹤變更。只要在指派項中加入包含金鑰 __changed__
的已變更對應,並將 true
傳遞給動態部分即可啟用變更追蹤。對應應包含任何變更欄位的名稱為金鑰,以及布林值 true 為值的。如果欄位未列在 __changed__
中,則它始終被視為未變更。
如果欄位未變更且即時認為動態表達式不再需要運算,則其在 dynamic
清單中的值會為 nil
。這個資訊可以用於避免將資料傳送給客戶端。
巢狀處理和指紋辨識
Phoenix.LiveView
也會追蹤即時範本間的變更。因此,如果你的檢視具有以下內容
<%= render "form.html", assigns %>
Phoenix 將能夠追蹤範本之間的靜態和動態內容,以及這些內容有哪些變更。呈示的巢狀 live
範本會以另一個 Phoenix.LiveView.Rendered
結構出現在 dynamic
清單中,必須遞迴處理。
然而,因為即時範本的呈示本身也可能是動態的,因此有必要區分呈示的是哪個即時範本。例如,想像以下程式碼
<%= if something?, do: render("one.html", assigns), else: render("other.html", assigns) %>
為了解決這個問題,所有 Phoenix.LiveView.Rendered
結構也包含一個指紋欄位來標識它。如果指紋相等,則表示你具有相同的範本,因此有可能只傳送它的變更。
理解
即時範本執行的另一個最佳化是追蹤理解。如果你的程式碼具有以下內容
<%= for point <- @points do %>
x: <%= point.x %>
y: <%= point.y %>
<% end %>
它不會呈示具有靜態和動態部分的所有點,而是傳回一個 Phoenix.LiveView.Comprehension
結構,其中包含跨所有點共用的靜態部分,以及要在靜態部分內插入的動態清單。如果 @points
是包含 %{x: 1, y: 2}
和 %{x: 3, y: 4}
的清單,上述表達式會傳回
%Phoenix.LiveView.Comprehension{
static: ["\n x: ", "\n y: ", "\n"],
dynamics: [
["1", "2"],
["3", "4"]
]
}
這讓即時範本可以大幅最佳化理解傳送的資料,因為靜態部分僅會傳送一次,不論項目數目為何。
動態清單總是 iodatas 或元件清單,因為我們不會在理解中執行變更追蹤。類似地,理解沒有指紋,因為它們僅在根部最佳化,因此像呈示中看到的條件評估是不可能的。傳回理解的動態欄位唯一可能出現的結果是 nil
。
元件
Live 也支援使用 Phoenix.LiveComponent
定義的有狀態元件。由於它們是有狀態的,所以總是以延遲方式由 diff 演算法處理。