跳至主要內容

在網頁中使用 HTML 插槽來渲染平台視圖

摘要

#

現在,Flutter 會將所有網頁平台視圖渲染在 DOM 中一致的位置,作為 flt-glass-pane 的直接子元素 (無論渲染後端是 htmlcanvaskit)。然後,平台視圖會使用標準 HTML 功能「插入」到應用程式 DOM 的正確位置。

在此變更之前,Flutter 網頁會變更平台視圖渲染內容的樣式,以將其定位/調整大小到可用的空間。現在情況已非如此。使用者現在可以決定他們希望如何利用框架分配給其平台視圖的空間。

內容

#

Flutter 框架會頻繁調整其渲染樹,以最佳化每個影格最終進行的繪圖操作。在網頁中,這些渲染樹的變更通常會導致 DOM 操作。

Flutter 網頁過去會將其平台視圖 (HtmlElementView 小工具) 直接渲染到 DOM 中相應的位置。

將某些 DOM 元素作為某些 DOM 操作的「目標」會導致這些元素失去其內部狀態。實際上,這表示 iframe 標籤將重新載入、video 播放器可能會重新啟動,或可編輯的表單可能會遺失其編輯內容。

現在,Flutter 使用單一、全應用程式範圍的 陰影根內的 插槽元素來渲染平台視圖。插槽元素可以在陰影 DOM 中新增/移除/移動,而不會影響底層插入的內容(該內容渲染在固定的位置)。

進行此變更是為了

  • 穩定 Flutter 網頁中平台視圖的行為。
  • 統一在網頁中針對兩個渲染後端 (htmlcanvaskit) 渲染平台視圖的方式。
  • 在 DOM 中提供可預測的位置,讓開發人員可以可靠地使用 CSS 來設定其平台視圖的樣式,並使用其他標準 DOM API,例如 querySelectorgetElementById

變更說明

#

Flutter 網頁應用程式現在會在一個常見的 陰影根中渲染,其中 插槽元素代表平台視圖。每個平台視圖的實際內容會渲染成上述陰影根的同層元素

之前

#
html
...

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

...

之後

#
html
...

<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,因此這被視為重大變更,並且會導致測試失敗。

移轉指南

#

程式碼

#

引擎可能會在主控台中列印類似以下的警告訊息

bash
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.

bash
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.widthstyle.height 設定為任何適當 (非空值) 的值。

例如,若要使根 html.Element 填滿框架分配的所有可用空間,請將其 style.widthstyle.height 屬性設定為 '100%'

dart
ui.platformViewRegistry.registerViewFactory(viewType, (int viewId) {
  final html.Element htmlElement = html.DivElement()
    // ..other props
    ..style.width = '100%'
    ..style.height = '100%';
  // ...
  return htmlElement;
});

如果使用其他技術來配置平台視圖 (例如 inset: 0),則將 widthheight 的值設為 auto 就足以停止警告。

請閱讀有關 CSS widthCSS height 的詳細資訊。

測試

#

在此變更之後,使用者的測試程式碼需要深入檢查應用程式陰影根的內容。所有平台視圖內容都會放置為 flt-glass-pane 的直接子元素,並包在 flt-platform-view 元素中。

請避免查看 flt-glass-pane 陰影根內部的內容,這被視為「私有實作細節」,其標記可以隨時變更,恕不另行通知。

(請參閱下方的相關 PR,以取得上述「移轉」的範例)。

時間軸

#

已在版本中推出:2.3.0-16.0.pre
在穩定版本中:2.5

參考

#

設計文件

相關問題

相關 PR