【AspNetCore 3.0] Blazorサーバコンポーネントレンダリング、RenderFragment、RenderTreeBuilder、CascadingValue / CascadingParameter等

まず、コンポーネント

Microsoftのサポート2つの成熟した技術のBlazor、カミソリテンプレートとSignalRは、二つの成分のミーティングポイントです。通常、我々はComponentBaseタイプから派生、または.razorファイルが作成され、それがコンポーネントを呼び出すことができます。2、メンテナンスコンポーネントの状態、これら二つの技術に基づいて、アセンブリは2つの機能、1、HTML生成されたフラグメントを有するであろう。ここでは、最も基本的な機能のためのコンポーネントを見てHTMLフラグメントを生成します。

二、RenderTreeBuilder、RenderFragment

私たちは、HTML文書がすべてのタグに対処するブラウザは、ドキュメントツリーからHTMLの段落は、常にはっきり木の手配があるだろうどんなににリンクされていることを知っています。行がある場合は、他の言葉では、我々は、この木に一緒に文字列にすべてのラベルを頼ることができますが、またBlazorコンポーネントで、そのようなラインは、このラインはRenderTreeBuilderあり、人々だけBlazorフレームワークのこのラインを取ります。

この注:特に指定のない限り、関連する次のコードは、の.csファイルに書かれて参照してください、Microsoft.AspNetCore.Components.ComponentBaseにコンポーネントクラスを継承しています。

コードでこの行の下を参照してください。BlazorクラスC#、追加、新しいアプリケーションプロジェクトを作成しMyComp、以下の方法を見つけ、それを上書きし、継承Microsoft.AspNetCore.Components.ComponentBaseを:

 protected override void BuildRenderTree(RenderTreeBuilder builder)
        {
            base.BuildRenderTree(builder);//加断点
        }

ブレークポイントを追加し、ページ\ Index.razor年にラインアイテムを追加します。<MyComp />
あなたが二回のコード実行したくない場合は、rendermodeでPages_Host.cshtmlでそれを変更

 @(await Html.RenderComponentAsync<App>(RenderMode.Server))

そこには出力されませんが、ブレークポイントにヒットが、F5の実行は、RenderTreeBuilderこの行は、本当に私たちのコンポーネントを張ら。
今度はあなたがRenderTreeBuilderを何ができるか見てみましょう。

  protected override void BuildRenderTree(RenderTreeBuilder builder)
        {
            builder.AddMarkupContent(0, "<span> BuildRenderTree  使用 AddMarkupContent 输出 Html 。</span>");
           // base.BuildRenderTree(builder);
        }

我々はより多くの我々はページ上のスパンを増やすよりも、見つけ、再び実行してください。のHTML出力は、RenderTreeBuilderプラスを呼び出すのさまざまな方法に頼っていたこと。ケースである基本原理コンポーネントは、RenderTreeBuilderはアドオンを通じて、BuildRenderTree方法の異なるコンポーネントを入力してください。..輸出に当社RenderTreeBuilderほしいですの一部にオープン..方法は、ビルダー、ブラウザへの最終的な出力へのメソッドの内部に搭載しました。

次に、我々は検討BuildRenderTree委員会を記述するために使用される方法を、私たちはこれがあることがわかりましたAction<RenderTreeBuilder>

私たちは、タイトルRenderFragmentにその定義を見て言及しました。

public delegate void RenderFragment(RenderTreeBuilder builder);//还是一个 Action<RenderTreeBuilder>,或者说,BuildRenderTree 就是一个RenderFragment

私たちが発見し、目の前にBuildRenderTreeblazor利用RenderTreeBuilderがBuildRenderTreeメソッドを呼び出すことがあるため、署名にまったく同じ、そしてRenderFragmentも呼ばれるのですか?

Index.razorコード内のいくつかを追加するために、私たちは一時的に組み立てMYCOMPを残しましょう

 @code{
     RenderFragment MyRender=(builder) => builder.AddMarkupContent(0, "<span>当前输出来自:Index.razor 组件, MyRender 字段。 </span>");
        
}

我々はMYCOMPコンポーネント、プラスラインの呼び出しを宣言する前にした後@MyRender
完全Index.razor

@page "/"

<MyComp />

 @MyRender

@code{
     
    RenderFragment MyRender = (builder) => builder.AddMarkupContent(0, "<div>当前输出来自:Index.razor 组件, MyRender 字段。 </div>");

}

二つの情報、出力して証明blazorテンプレートRenderFragmentを識別し、自動的に呼び出すことができます。
我々 (Index.razor)RenderFragmentアセンブリテンプレートに記述されているので、もちろん、あなたが一緒に文字列を置くことができない他の方法があります。

 RenderFragment AnotherRender =@<div>模板写法的RenderFragment</div>;

プラスの呼び出しは@AnotherRender、次の3つの情報を実行しています。

この時点で、我々はRenderFragmentの大まかなアイデアを持って、それが私たちの出力を梱包内部関数です。私たちは、テンプレートを使用することができ@xxxrenderて、C#の環境の中で我々はできる、代わりにその出力を拡大していきますxxxrender(builder)(例えばBuildRenderTreeメソッド内で呼び出しなど)の呼び出し形式。私たちが使用できるように、それはコンポーネント内にあること、デリゲート関数自体であるため、また、自由の要素、コンテンツおよび出力ロジックの完全な再利用の間で渡すことができます。
一方、より良い満たすRenderFragmentを使用するためには、BlazorもRenderFragment、工場出荷時のデリゲートを提供します 、すなわちのFunc <TValue、RenderFragment>次の一般的な使い方

//模板中(Index.razor)
RenderFragment<object> RenderValue =value=> @<div> render value :@value</div>;

コール@RenderValue (123)などBuildRenderTree方法と同様に、C#コード場合RenderValue (123)(builder)

コンパイル時の.g.csがobj /デバッグ/ netcoreapp3.0 /かみそりで対応するコードの位置を生成するに* .razor対では、よりオープンな外観することができます。

三、RenderFragmentいくつかの使い方

1、htmlのは、我々は例えば、ラベルの内容のペアで追加することができ<div>123</div>、デフォルトのコンポーネントは、このタイプの動作をサポートしていない、我々は、パッケージのラベル内RenderFragment内容にする必要があります。

レッツ・ゴーバックMYCOMPコンポーネントクラス、属性を追加します

[Parameter] public RenderFragment ChildContent{ get; set; }

Index.razor

<MyComp><div> 组件标记内部</div></MyComp>

このとき、直接実行で、内部コンポーネントが情報を出力しない、それはBuildRenderTreeで行う必要があります

  protected override void BuildRenderTree(RenderTreeBuilder builder)
        {
          ChildContent?.Invoke(builder);
          
            base.BuildRenderTree(builder);
        }

コンポーネントタグ内のセグメントは、ChildContentにパックされ、我々はそれを明示的に呼び出す必要があるので、別のセグメントとなっています。
ChildContentは特別な名前です

図2に示すように、複数のコンポーネントにRenderFragment

   [Parameter] public RenderFragment Fragment1 { get; set; }
        [Parameter] public RenderFragment Fragment2 { get; set; }

この時点で、呼び出しは調整する必要がある、またはフレームワークは、パッケージングセグメントの内容を知らないにどのプロパティで

 <MyComp>
        <Fragment1>

            <div> Fragment1 </div>
        </Fragment1>
        <Fragment1>
            <div> Fragment1.1  </div>

        </Fragment1>
        <Fragment2>
            <div> Fragment2  </div>

        </Fragment2>
  
    </MyComp>

ここでは、意図的にあなたが結果を見ることができ、Fragment1プロセスを繰り返しました。

3、パラメータを持つRenderFragment
コード:

[Parameter] public RenderFragment<MyComp> ChildContent { get; set; }

呼び出しやパラメータの受け渡し

  <MyComp Context="self" > //<ChildContent>
       @self.GetType()
      
    </MyComp>  //</ChildContent>

図4に示すように、内部標識された成分は、さらなる成分を含む、他の構文かみそり基本的なサポートをRenderFragmentプロパティを使用したパラメータに加えて、オープン宣言しました。
そのようなものとして

  <MyComp>
         <CompA />
          <CompB> ...... </CompB>
</MyComp>

若しくは

  <MyComp>
       <Fragment1>
         <CompA />
      </Fragment1>

          <Fragment2>
          <CompB> ...... </CompB>
          </Fragment2>
</MyComp>

それは思われるが、宣言型のマークアップコードは非常に似ていますが、かなりの違いがあります。
私たちは宣言タグの属性パラメータを使用すると、我々はRenderFragmentを生成して、対応するプロパティに割り当てています。
我々は、コンポーネントタグステートメントを使用する場合、我々はコンポーネントインスタンスを作成し、次にそれを呼び出すされ、アセンブリは、出力構成要素が存在する位置に挿入されます。
パラメータのプロパティ(RenderFragment)がコンポーネントに属し、コンポーネントは、互いに関係の属性がクリアタイプ「=」メンバーシップです。
マークの内部コンポーネントの他のコンポーネントに何度だけのコードで出力フラグメントのいくつか、そうでない場合は、いくつかの処理を再利用するために、はっきりとコンポーネント間の関係を知っていません。

四、CascadingValue / CascadingParameter

組み立て後少数、手動@ref指定するために使用することができる場合に乗算した後にコンポーネント間およびコンポーネント間のデータ共有および転送の関係は明確ではない良い方法@ref、非常に煩雑となり、増加しました。CascadingValueコンポーネントと対応するプロパティ[CascadingParameter]は発生し、この問題を解決することです。

CascadingValue内のすべてのコンポーネントは、[CascadingParameter]成分の特性に限り添付として、子供を含み、コンテンツの値に互換性がある、このプロパティが割り当てられます。

そのような定義するコンポーネントを受信するようCascadingValue属性

        [CascadingParameter] public  int Value { get; set; }
        [CascadingParameter] public string SValue { get; set; }

//修改下输出
    protected override void BuildRenderTree(RenderTreeBuilder builder)
        {
            builder.AddMarkupContent(0, $"<div>CascadingValue: {Value},{SValue} </div>");// 一个int,一个string
            ChildContent?.Invoke(this)(builder);//加载下级组件
            base.BuildRenderTree(builder);
        }

かみそりのページで

 <CascadingValue Value="123"> //int
      <MyComp>
                         <MyComp></MyComp>
                     </MyComp>
</CascadingValue >

実行後、我々は2つの成分がint型の値123が捕獲されていることがわかります
今CascadingValueを追加します

 <CascadingValue Value="123"> //int
<CascadingValue Value="@("aaaa")"> //string
      <MyComp>
                         <MyComp></MyComp>
                     </MyComp>
</CascadingValue >
</CascadingValue >

CascadingValue 2つの値の二つの異なるタイプに属し、それはそう、非常に幅広い用途シナリオを任意の出力を生成しない便利で強力なHTML自体、各成分の二つの性質に捕捉しました。アセンブリような公式手段CascadingValue /パラメータの完全なモデルが提供されている形態、別の例では、あなたが簡単に定義することができ、インタフェース関係サンズアセンブリ処理デフォルトが含ましない[CascadingParameter] public ComponentBase Parent{get;set;}専用の親受信コンポーネント、表に処理類似/列等コンポーネントの関係。

V.の概要

コンポーネントは、独自BuildRenderTree法(RenderFragment)サービス、コンポーネントのプロパティに、種々の方法のために、そうアセンブリ本質的にラッパークラスRenderFragmentある、RenderFragmentに環境を準備するために行うように設計されています。システムの構成要素が順番に各成分RenderTreeBuilderによって呼び出され、出力内容を収集し、そして最終的に内部システム出力が完了します。
図1に示すように、.Razorファイルは、コンポーネントクラスにコンパイルされる(OBJ /デバッグ/ netcore3.0 /かみそり/ ...)
2、システムのコンポーネントは、コンポーネントのインスタンスにそれを取る、RenderTreeBuilderを作成
自体を呼び出し、RenderTreeBuilderを使用して3、コンポーネントインスタンスBuildRenderTree 。
コンポーネントの状態変化、再び出力4.待ち。

おすすめ

転載: www.cnblogs.com/cerl/p/11834510.html