1. 程式人生 > WINDOWS開發 >C# 環球世界註冊賬號系列-IO篇 環球世界程式碼的使用

C# 環球世界註冊賬號系列-IO篇 環球世界程式碼的使用

C# 環球世界註冊賬號系列-IO篇 環球世界程式碼的使用

前一篇Yew框架(一) 應用初始化過程我們瞭解一應用啟動的過程,後續我將探索Yew中的一些功能是如何實現的,先來看看 子元件的建立渲染過程。

Yew 支援在元件的檢視中巢狀元件,支援給子元件傳遞屬性,下圖是測試程式碼擴充套件前後的對比:技術分享圖片

上面的程式碼主要是建立VChild物件,不是特別難,但要看懂它做了什麼,為什麼要這樣做,還得先看 Properties 巨集對元件的屬性做了什麼。

Properties 屬性

這是我們自定義的Button元件的屬性宣告:

技術分享圖片

擴充套件後:

技術分享圖片

程式碼一下變多了。

首先是定義了一個 PropsWrapper,包含兩個屬性,但屬性的型別都為Option型別,並且實現了Default特性,從後面的程式碼可以看到它就是PropsBuilder 用來儲存過程資訊的。

定義了兩個結構體,都實現PropsBuilderStep特性,定義一個PropsBuilder結構體,有一個泛型引數,引數實現PropsBuilderStep。這是一個狀態機在Rust的實現模式,用泛型引數來表示構建器的狀態,通過構建器的方法來進行狀態遷移,不同的狀態可以呼叫不同的方法。

因為我們只有兩個屬性,所以 PropsBuilderStep 只有兩個狀態。PropsBuilderStep_missing_required_prop_text 是初始狀態,該狀態來可以呼叫 onclick 和 text 兩個方法,來配置 builder,資訊儲存在 Builder 內部的 PropsWarpper 中。

值得注意的是,Yew 元件的屬性是可以不傳的,但可不可以不傳是由屬性的定義者來決定的,而不是呼叫者來決定的。如果定義一個屬性為必傳,那麼呼叫者必須傳入一個合適的值。如果定義為可不傳,呼叫者可以決定傳還是不傳。Builder 中自動生成的方法引數上有區別,如果是可以不傳的屬性,其引數是Option型別。

為Props結構體實現 Properties 屬性,只有一個builder方法,用來建立該屬性的 Builder,最後由呼叫該Builder的build方法(該方法只能在 PropsBuilderStep_build 狀態下呼叫,Builder的方法是逆序生成的,最後一個方法呼叫完成後進入 build 狀態),用 PropsWrapper記憶體儲的值來建立一個 Props 物件。

現在接著看 VChild 的建立。

建立 VChild 物件

VChild物件有一個泛型引數,是子元件的型別,這裡是 Button。擴充套件後的建立程式碼如下:

技術分享圖片

呼叫 VChild::new() 方法,傳入三個引數,第一個是通過構建器構建的元件屬性,第二個是預設的 NodeRef, 第三個是 None。

從程式碼中看到構建方法的引數都用 VComp 的transform方法進行了轉換,這是為何?

Transformer

從註釋中得知這個特性功能是用來把屬性(呼叫者傳入的屬性值)轉換了期待的型別(子元件屬性物件中對應屬性期待的型別)。

技術分享圖片

VComp 實現多種型別轉換,讓父元件可以有多種傳遞屬性給子元件的方式,簡單說就是提供了“語法糖”。從 FROM 到 TO,表示當子元件的屬性期待的是 TO 型別時,父元件可以為其提供 FROM 型別,由 Transformer 自動轉換為 TO 型別,賦值給屬性。

技術分享圖片

搜尋原始碼,VComp一共有7個實現:

  • 子元件需要什麼,父元件就傳什麼;
  • 當子元件需要 T 型別時,可以傳入 &T,要求 T 具有 Clone 特性;
  • 如果子元件需要的是 String,父元件可以傳入 &str;
  • 如果子元件需要的是 Option<T> 型別,父元件可以只傳入 T 或 &T(要求 T 具有 Clone 特性)型別;
  • 如果子元件需要的是 Option<String> 型別,父元件可以傳入 &str 或 Option<&str>。

在示例中,我們需要的是一個 String 型別和一個 Option<Callback<()>> 型別,父元件傳入的是 &str 和 Callback<()> 型別。經過Transformer 轉換成了我們期望的型別。

VChild::new()

技術分享圖片

技術分享圖片

這個方法很簡單,就是建立一個 VChild 物件。

轉化為 VComp

第一張圖51行,表示最終會呼叫VNode::from方法:

技術分享圖片

內部先呼叫 VComp::from 方法將 VChild 轉換為 VComp,最終轉換為 VNode::VComp。

技術分享圖片

如此看來,VChild 也是一個備胎,它也只是在中途被用一下,在這裡就被拋棄了,才創建出來沒有兩分鐘,哈哈哈!重頭在 VComp::new()

技術分享圖片

技術分享圖片

果然如此,程式碼長度說明一切!

Generator

用來根據 GeneratorType 渲染子元件檢視並掛載到 Dom 的閉包。GeneratorType 有兩種情況,一種是建立元件物件並掛載到節點,另一種是之前已經掛載過該元件物件了,只需要更新元件的屬性。

閉包內的程式碼已經很熟悉了(參考Yew框架(一) 應用初始化過程),第一種情況下,和掛載任意VNode類似,第二種情況下發出一個更新指令到排程器,會先更新元件Scope的狀態(期間會呼叫元件的 change 方法)並重新渲染檢視。

建立一個可以建立或更新子元件的閉包,但並未執行,將VComp置為 Unmounted的狀態。在渲染檢視時,會根據具體情況決定如何來渲染該VComp。