在網頁中使用 HTML 插槽來渲染平台視圖
摘要
#現在,Flutter 會將所有網頁平台視圖渲染在 DOM 中一致的位置,作為 flt-glass-pane
的直接子元素 (無論渲染後端是 html
或 canvaskit
)。然後,平台視圖會使用標準 HTML 功能「插入」到應用程式 DOM 的正確位置。
在此變更之前,Flutter 網頁會變更平台視圖渲染內容的樣式,以將其定位/調整大小到可用的空間。現在情況已非如此。使用者現在可以決定他們希望如何利用框架分配給其平台視圖的空間。
內容
#Flutter 框架會頻繁調整其渲染樹,以最佳化每個影格最終進行的繪圖操作。在網頁中,這些渲染樹的變更通常會導致 DOM 操作。
Flutter 網頁過去會將其平台視圖 (HtmlElementView
小工具) 直接渲染到 DOM 中相應的位置。
將某些 DOM 元素作為某些 DOM 操作的「目標」會導致這些元素失去其內部狀態。實際上,這表示 iframe
標籤將重新載入、video
播放器可能會重新啟動,或可編輯的表單可能會遺失其編輯內容。
現在,Flutter 使用單一、全應用程式範圍的 陰影根內的 插槽元素來渲染平台視圖。插槽元素可以在陰影 DOM 中新增/移除/移動,而不會影響底層插入的內容(該內容渲染在固定的位置)。
進行此變更是為了
- 穩定 Flutter 網頁中平台視圖的行為。
- 統一在網頁中針對兩個渲染後端 (
html
和canvaskit
) 渲染平台視圖的方式。 - 在 DOM 中提供可預測的位置,讓開發人員可以可靠地使用 CSS 來設定其平台視圖的樣式,並使用其他標準 DOM API,例如
querySelector
和getElementById
。
變更說明
#Flutter 網頁應用程式現在會在一個常見的 陰影根中渲染,其中 插槽元素代表平台視圖。每個平台視圖的實際內容會渲染成上述陰影根的同層元素。
之前
#...
<flt-glass-pane>
...
<div id="platform-view">Contents</div> <!-- canvaskit -->
<!-- OR -->
<flt-platform-view>
#shadow-root
| <div id="platform-view">Contents</div> <!-- html -->
</flt-platform-view>
...
</flt-glass-pane>
...
之後
#...
<flt-glass-pane>
#shadow-root
| ...
| <flt-platform-view-slot>
| <slot name="platform-view-1" />
| </flt-platform-view-slot>
| ...
<flt-platform-view slot="platform-view-1">
<div id="platform-view">Contents</div>
</flt-platform-view>
...
</flt-glass-pane>
...
在此變更之後,當框架需要移動 DOM 節點時,它會對 flt-platform-view-slot
進行操作,而這些元素僅包含一個 slot
元素。插槽會將 flt-platform-view
元素中定義的內容投影到陰影根外部。flt-platform-view
元素永遠不會成為框架的 DOM 操作目標,因此可以防止重新載入問題。
從應用程式的角度來看,此變更具備透明性。但是,由於某些測試會假設 Flutter 網頁應用程式的內部 DOM,因此這被視為重大變更,並且會導致測試失敗。
移轉指南
#程式碼
#引擎可能會在主控台中列印類似以下的警告訊息
Height of Platform View type: [$viewType] may not be set. Defaulting to `height: 100%`.
Set `style.height` to any appropriate value to stop this message.
或
Width of Platform View type: [$viewType] may not be set. Defaulting to `width: 100%`.
Set `style.width` to any appropriate value to stop this message.
先前,PlatformViewFactory
函式傳回的內容會由框架調整大小和定位。現在,Flutter 會改為調整大小並定位 <flt-platform-view-slot>
,這是內容投影到的插槽的父元素。
若要停止上述警告,平台視圖需要將其根元素的 style.width
和 style.height
設定為任何適當 (非空值) 的值。
例如,若要使根 html.Element
填滿框架分配的所有可用空間,請將其 style.width
和 style.height
屬性設定為 '100%'
ui.platformViewRegistry.registerViewFactory(viewType, (int viewId) {
final html.Element htmlElement = html.DivElement()
// ..other props
..style.width = '100%'
..style.height = '100%';
// ...
return htmlElement;
});
如果使用其他技術來配置平台視圖 (例如 inset: 0
),則將 width
和 height
的值設為 auto
就足以停止警告。
請閱讀有關 CSS width
和 CSS height
的詳細資訊。
測試
#在此變更之後,使用者的測試程式碼不需要深入檢查應用程式陰影根的內容。所有平台視圖內容都會放置為 flt-glass-pane
的直接子元素,並包在 flt-platform-view
元素中。
請避免查看 flt-glass-pane
陰影根內部的內容,這被視為「私有實作細節」,其標記可以隨時變更,恕不另行通知。
(請參閱下方的相關 PR,以取得上述「移轉」的範例)。
時間軸
#已在版本中推出:2.3.0-16.0.pre
在穩定版本中:2.5
參考
#設計文件
相關問題
相關 PR
- flutter/engine#25747:推出此功能。
- flutter/flutter#82926:調整
flutter
測試。 - flutter/plugins#3964:調整
plugins
程式碼。 - flutter/packages#364:調整
packages
程式碼。
除非另有說明,否則本網站上的文件反映 Flutter 的最新穩定版本。頁面最後更新於 2024-04-04。 檢視原始碼 或回報問題。