다음을 통해 공유


Blazor를 사용하여 재사용 가능한 UI 구성 요소 빌드

이 콘텐츠는 Blazor 또는 오프라인으로 읽을 수 있는 다운로드 가능한 무료 PDF로 제공되는 for ASP NET Web Forms Developers for Azure eBook에서 발췌한 것입니다.

Blazor-for-ASP-NET-Web-Forms-Developers eBook 표지 썸네일.

ASP.NET Web Forms의 이점 중 하나는 이를 통해 재사용 가능한 UI(사용자 인터페이스) 코드 조각을 재사용 가능한 UI 컨트롤로 캡슐화할 수 있는 방식입니다. 사용자 지정 사용자 정의 컨트롤은 .ascx 파일을 사용하여 태그에서 정의할 수 있습니다. 전체 디자이너 지원으로 코드에서 정교한 서버 컨트롤을 빌드할 수도 있습니다.

Blazor는 ‘구성 요소’를 통한 UI 캡슐화도 지원합니다. 구성 요소는 다음과 같습니다.

  • UI의 자체 포함 청크입니다.
  • 자체 상태 및 렌더링 논리를 유지 관리합니다.
  • UI 이벤트 처리기를 정의하고 입력 데이터에 바인딩하고 자체 수명 주기를 관리할 수 있습니다.
  • 일반적으로 Razor 구문을 사용하여 .razor 파일에 정의됩니다.

Razor 소개

Razor는 HTML 및 C#을 기반으로 하는 간단한 태그 템플릿 언어입니다. Razor를 사용하면 태그와 C# 코드 간에 원활하게 전환하여 구성 요소 렌더링 논리를 정의할 수 있습니다. .razor 파일이 컴파일될 때 렌더링 논리는 .NET 클래스에서 구조화된 방식으로 캡처됩니다. 컴파일된 클래스의 이름은 .razor 파일 이름에서 가져옵니다. 네임스페이스는 프로젝트 및 폴더 경로의 기본 네임스페이스에서 가져옵니다. 또는 @namespace 지시문을 사용하여 네임스페이스를 명시적으로 지정할 수 있습니다(아래 Razor 지시문 참조).

구성 요소의 렌더링 논리는 C#을 사용하여 추가된 동적 논리와 함께 일반 HTML 태그를 사용하여 작성됩니다. @ 문자는 C#으로 전환하는 데 사용됩니다. Razor는 일반적으로 HTML로 다시 전환한 경우를 파악하는 데 유용합니다. 예를 들어 다음 구성 요소는 현재 시간을 사용하여 <p> 태그를 렌더링합니다.

<p>@DateTime.Now</p>

C# 식의 시작과 끝을 명시적으로 지정하려면 괄호를 사용합니다.

<p>@(DateTime.Now)</p>

Razor를 통해 렌더링 논리에서 C# 제어 흐름을 쉽게 사용할 수도 있습니다. 예를 들어 다음과 같이 일부 HTML을 조건부로 렌더링할 수 있습니다.

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}

또는 다음과 같이 일반적인 C# foreach 루프를 사용하여 항목 목록을 생성할 수 있습니다.

<ul>
@foreach (var item in items)
{
    <li>@item.Text</li>
}
</ul>

ASP.NET Web Forms의 지시문 같은 Razor 지시문은 Razor 구성 요소 컴파일 방법의 다양한 측면을 제어합니다. 예제에는 구성 요소의 다음 항목이 포함됩니다.

  • 네임스페이스
  • 기본 클래스
  • 구현된 인터페이스
  • 제네릭 매개 변수
  • 가져온 네임스페이스
  • 경로

Razor 지시문은 @ 문자로 시작하고 일반적으로 파일의 시작 부분에 있는 새 줄의 시작 부분에서 사용됩니다. 예를 들어 @namespace 지시문은 구성 요소의 네임스페이스를 정의합니다.

@namespace MyComponentNamespace

다음 표에는 Blazor에서 사용되는 다양한 Razor 지시문 및 해당 ASP.NET Web Forms 항목(있는 경우)이 요약되어 있습니다.

지시문 설명 예시 해당 Web Forms 항목
@attribute 구성 요소에 클래스 수준 특성 추가 @attribute [Authorize] 없음
@code 구성 요소에 클래스 멤버 추가 @code { ... } <script runat="server">...</script>
@implements 지정된 인터페이스 구현 @implements IDisposable 코드 숨김 사용
@inherits 지정된 기본 클래스에서 상속 @inherits MyComponentBase <%@ Control Inherits="MyUserControlBase" %>
@inject 구성 요소에 서비스 삽입 @inject IJSRuntime JS 없음
@layout 구성 요소의 레이아웃 구성 요소 지정 @layout MainLayout <%@ Page MasterPageFile="~/Site.Master" %>
@namespace 구성 요소의 네임스페이스 설정 @namespace MyNamespace 없음
@page 구성 요소의 경로 지정 @page "/product/{id}" <%@ Page %>
@typeparam 구성 요소의 제네릭 형식 매개 변수 지정 @typeparam TItem 코드 숨김 사용
@using 범위에 가져올 네임스페이스 지정 @using MyComponentNamespace web.config에 네임스페이스 추가

또한 Razor 구성 요소는 요소의 ‘지시문 특성’을 광범위하게 사용하여 구성 요소 컴파일 방법의 다양한 측면을 제어합니다(이벤트 처리, 데이터 바인딩, 구성 요소 및 요소 참조 등). 지시문 특성은 모두 괄호 내 값이 선택 사항인 일반적인 제네릭 구문을 따릅니다.

@directive(-suffix(:name))(="value")

다음 표에는 Blazor에서 사용되는 Razor 지시문의 다양한 특성이 요약되어 있습니다.

attribute 설명 예시
@attributes 특성 사전 렌더링 <input @attributes="ExtraAttributes" />
@bind 양방향 데이터 바인딩 만들기 <input @bind="username" @bind:event="oninput" />
@on{event} 지정된 이벤트의 이벤트 처리기 추가 <button @onclick="IncrementCount">Click me!</button>
@key diff 알고리즘에서 컬렉션에서 요소를 유지하는 데 사용할 키 지정 <DetailsEditor @key="person" Details="person.Details" />
@ref 구성 요소 또는 HTML 요소에 대한 참조 캡처 <MyDialog @ref="myDialog" />

Blazor에서 사용되는 다양한 지시문 특성(@onclick, @bind, @ref 등)은 아래 섹션과 이후 장에서 설명합니다.

.aspx.ascx 파일에서 사용되는 대부분 구문은 Razor에 병렬 구문이 있습니다. 다음은 ASP.NET Web Forms 및 Razor의 간단한 구문 비교입니다.

기능 웹 양식 구문 면도기 구문
지시문 <%@ [directive] %> <%@ Page %> @[directive] @page
코드 블록 <% %> <% int x = 123; %> @{ } @{ int x = 123; }

(HTML 인코딩)
<%: %> <%:DateTime.Now %> 암시적: @
명시적: @()
@DateTime.Now
@(DateTime.Now)
설명 <%-- --%> <%-- Commented --%> @* *@ @* Commented *@
데이터 바인딩 <%# %> <%# Bind("Name") %> @bind <input @bind="username" />

Razor 구성 요소 클래스에 멤버를 추가하려면 @code 지시문을 사용합니다. 이 기술은 ASP.NET Web Forms 사용자 정의 컨트롤 또는 페이지에서 <script runat="server">...</script> 블록을 사용하는 것과 비슷합니다.

@code {
    int count = 0;

    void IncrementCount()
    {
        count++;
    }
}

Razor는 C#을 기반으로 하기 때문에 C# 프로젝트(.csproj) 내에서 컴파일해야 합니다. Visual Basic 프로젝트(.vbproj)에서 .razor 파일을 컴파일할 수 없습니다. Blazor 프로젝트에서 Visual Basic 프로젝트를 계속 참조할 수 있습니다. 반대의 경우도 마찬가지입니다.

전체 Razor 구문 참조에 관해서는 ASP.NET Core의 Razor 구문 참조를 참조하세요.

구성 요소 사용

일반 HTML 외에도 구성 요소는 렌더링 논리의 일부로 다른 구성 요소를 사용할 수 있습니다. Razor에서 구성 요소를 사용하는 구문은 ASP.NET Web Forms 앱에서 사용자 정의 컨트롤을 사용하는 것과 비슷합니다. 구성 요소는 구성 요소의 형식 이름과 일치하는 요소 태그를 사용하여 지정합니다. 예를 들어 다음과 같이 Counter 구성 요소를 추가할 수 있습니다.

<Counter />

ASP.NET Web Forms와 달리 Blazor의 구성 요소는 다음과 같습니다.

  • 요소 접두사(예: asp:)를 사용하지 않습니다.
  • 페이지 또는 web.config에 등록하지 않아도 됩니다.

정확히 일치하므로 Razor 구성 요소를 .NET 형식처럼 생각하세요. 구성 요소가 포함된 어셈블리가 참조되는 경우 구성 요소를 사용할 수 있습니다. 구성 요소의 네임스페이스를 범위로 가져오려면 @using 지시문을 적용합니다.

@using MyComponentLib

<Counter />

기본 Blazor 프로젝트에서 알아본 것처럼 일반적으로 @using 지시문을 _Imports.razor 파일에 넣으므로 동일한 디렉터리 및 하위 디렉터리에 있는 모든 .razor 파일로 지시문을 가져옵니다.

구성 요소의 네임스페이스가 범위에 없는 경우 C#에서 할 수 있는 것처럼 전체 형식 이름을 사용하여 구성 요소를 지정할 수 있습니다.

<MyComponentLib.Counter />

구성 요소에서 페이지 제목 수정

SPA 스타일 앱을 빌드할 때는 대부분 전체 페이지를 다시 로드하지 않고 페이지의 일부를 다시 로드합니다. 이 경우에도 현재 로드된 구성 요소에 따라 페이지 제목을 변경하면 도움이 될 수 있습니다. 구성 요소의 Razor 페이지에 <PageTitle> 태그를 포함하면 이 작업을 수행할 수 있습니다.

@page "/"
<PageTitle>Home</PageTitle>

이 구성 요소의 내용은 동적일 수 있습니다(예: 현재 메시지 수 표시).

<PageTitle>@MessageCount messages</PageTitle>

특정 페이지의 여러 구성 요소에 <PageTitle> 태그가 포함되어 있는 경우 마지막 항목만 표시됩니다(각 구성 요소는 이전 구성 요소를 덮어쓰기 때문입니다).

구성 요소 매개 변수

ASP.NET Web Forms에서 public 속성을 사용하여 매개 변수 및 데이터를 컨트롤로 이동할 수 있습니다. 이 속성은 특성을 사용하여 태그에서 설정하거나 코드에서 직접 설정할 수 있습니다. Razor 구성 요소는 비슷한 방식으로 작동하지만, 구성 요소 속성은 구성 요소 매개 변수로 간주되는 [Parameter] 특성으로도 표시되어야 합니다.

다음 Counter 구성 요소는 단추를 클릭할 때마다 IncrementAmount가 증분되어야 하는 양을 지정하는 데 사용할 수 있는 Counter라는 구성 요소 매개 변수를 정의합니다.

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    int currentCount = 0;

    [Parameter]
    public int IncrementAmount { get; set; } = 1;

    void IncrementCount()
    {
        currentCount+=IncrementAmount;
    }
}

Blazor에서 구성 요소 매개 변수를 지정하려면 ASP.NET Web Forms와 같이 특성을 사용합니다.

<Counter IncrementAmount="10" />

쿼리 문자열 매개 변수

Razor 구성 요소는 매개 변수 원본으로서 렌더링되는 페이지의 쿼리 문자열에 있는 값을 활용할 수도 있습니다. 이 기능을 사용하려면 매개 변수에 [SupplyParameterFromQuery] 특성을 추가합니다. 예를 들어 다음 매개 변수 정의는 ?IncBy=2 형식의 요청에서 관련 값을 가져옵니다.

[Parameter]
[SupplyParameterFromQuery(Name = "IncBy")]
public int IncrementAmount { get; set; } = 1;

Name 특성에 사용자 지정 [SupplyParameterFromQuery]을 제공하지 않으면 기본적으로 속성 이름(이 경우에는 IncrementAmount)과 일치하게 됩니다.

구성 요소 및 오류 경계

기본적으로 Blazor 앱은 처리되지 않은 예외를 검색하고 페이지 맨 아래에 오류 메시지를 추가 세부 정보 없이 표시합니다. 처리되지 않은 오류의 영향을 받는 앱의 부분을 제한하려면(예를 들어 영향받는 부분을 단일 구성 요소로 제한하려면) <ErrorBoundary> 태그를 구성 요소 선언 주위에 래핑하면 됩니다.

예를 들어 Counter 구성 요소에서 잠재적 예외를 방지하려면, <ErrorBoundary>에서 이를 선언하면 됩니다. 선택 사항으로 예외가 있을 때 표시할 메시지를 지정할 수도 있습니다.

<ErrorBoundary>
    <ChildContent>
        <Counter />
    </ChildContent>
    <ErrorContent>
        Oops! The counter isn't working right now; please try again later.
    </ErrorContent>
</ErrorBoundary>

사용자 지정 오류 내용을 지정할 필요가 없다면 구성 요소를 직접 래핑할 수 있습니다.

<ErrorBoundary>
  <Counter />
</ErrorBoundary>

래핑된 구성 요소에서 처리되지 않은 예외가 발생하면 "오류가 발생했습니다."라는 기본 메시지가 표시됩니다.

이벤트 처리기

ASP.NET Web Forms 및 Blazor는 둘 다 UI 이벤트 처리를 위한 이벤트 기반 프로그래밍 모델을 제공합니다. 해당 이벤트의 예로는 단추 클릭 및 텍스트 입력이 있습니다. ASP.NET Web Forms에서 HTML 서버 컨트롤을 사용하여 DOM에서 공개하는 UI 이벤트를 처리하거나 웹 서버 컨트롤에서 공개하는 이벤트를 처리할 수 있습니다. 이벤트는 양식 다시 게시 요청을 통해 서버에 표시됩니다. 다음 Web Forms 단추 클릭 예제를 살펴봅니다.

Counter.ascx

<asp:Button ID="ClickMeButton" runat="server" Text="Click me!" OnClick="ClickMeButton_Click" />

Counter.ascx.cs

public partial class Counter : System.Web.UI.UserControl
{
    protected void ClickMeButton_Click(object sender, EventArgs e)
    {
        Console.WriteLine("The button was clicked!");
    }
}

Blazor에서 양식 @on{event}의 지시문 특성을 사용하여 직접 DOM UI 이벤트의 처리기를 등록할 수 있습니다. {event} 자리 표시자는 이벤트 이름을 나타냅니다. 예를 들어 다음과 같이 단추 클릭을 수신 대기할 수 있습니다.

<button @onclick="OnClick">Click me!</button>

@code {
    void OnClick()
    {
        Console.WriteLine("The button was clicked!");
    }
}

이벤트 처리기는 선택적 이벤트 관련 인수를 수락하여 이벤트에 관한 자세한 정보를 제공할 수 있습니다. 예를 들어 마우스 이벤트는 MouseEventArgs 인수를 사용할 수 있지만 필수는 아닙니다.

<button @onclick="OnClick">Click me!</button>

@code {
    void OnClick(MouseEventArgs e)
    {
        Console.WriteLine($"Mouse clicked at {e.ScreenX}, {e.ScreenY}.");
    }
}

이벤트 처리기의 메서드 그룹을 참조하는 대신 람다 식을 사용할 수 있습니다. 람다 식을 사용하여 다른 범위 내 값을 둘러쌀 수 있습니다.

@foreach (var buttonLabel in buttonLabels)
{
    <button @onclick="() => Console.WriteLine($"The {buttonLabel} button was clicked!")">@buttonLabel</button>
}

이벤트 처리기는 동기적 또는 비동기적으로 실행될 수 있습니다. 예를 들어 다음 OnClick 이벤트 처리기는 비동기적으로 실행됩니다.

<button @onclick="OnClick">Click me!</button>

@code {
    async Task OnClick()
    {
        var result = await Http.GetAsync("api/values");
    }
}

이벤트가 처리된 후 구성 요소는 구성 요소 상태 변경을 설명하도록 렌더링됩니다. 비동기 이벤트 처리기를 사용하면 구성 요소는 처리기 실행이 완료된 직후에 렌더링됩니다. 구성 요소는 비동기 가 완료된 후 ‘다시’ 렌더링됩니다.Task 이 비동기 실행 모드는 비동기 Task가 진행되는 동안 몇 가지 적절한 UI를 렌더링할 기회를 제공합니다.

<button @onclick="ShowMessage">Get message</button>

@if (showMessage)
{
    @if (message == null)
    {
        <p><em>Loading...</em></p>
    }
    else
    {
        <p>The message is: @message</p>
    }
}

@code
{
    bool showMessage = false;
    string message;

    public async Task ShowMessage()
    {
        showMessage = true;
        message = await MessageService.GetMessageAsync();
    }
}

구성 요소는 EventCallback<TValue> 형식의 구성 요소 매개 변수를 정의하여 자체 이벤트를 정의할 수도 있습니다. 이벤트 콜백은 선택적 인수, 동기나 비동기, 메서드 그룹 또는 람다 식과 같은 DOM UI 이벤트 처리기의 모든 변형을 지원합니다.

<button class="btn btn-primary" @onclick="OnClick">Click me!</button>

@code {
    [Parameter]
    public EventCallback<MouseEventArgs> OnClick { get; set; }
}

데이터 바인딩

Blazor는 UI 구성 요소의 데이터를 구성 요소 상태에 바인딩하는 간단한 메커니즘을 제공합니다. 이 접근 방식은 데이터 소스의 데이터를 UI 컨트롤에 바인딩하는 ASP.NET Web Forms의 기능과 다릅니다. 데이터 처리 섹션에서 다양한 데이터 소스의 데이터를 처리하는 방법을 설명합니다.

UI 구성 요소에서 구성 요소 상태로 양방향 데이터 바인딩을 만들려면 @bind 지시문 특성을 사용합니다. 다음 예제에서 확인란의 값은 isChecked 필드에 바인딩됩니다.

<input type="checkbox" @bind="isChecked" />

@code {
    bool isChecked;
}

구성 요소가 렌더링되면 확인란의 값은 isChecked 필드의 값으로 설정됩니다. 사용자가 확인란을 토글하면 onchange 이벤트가 발생하고 isChecked 필드가 새 값으로 설정됩니다. 이 경우 @bind 구문은 다음 태그와 동일합니다.

<input value="@isChecked" @onchange="(UIChangeEventArgs e) => isChecked = e.Value" />

바인딩에 사용되는 이벤트를 변경하려면 @bind:event 특성을 사용합니다.

<input @bind="text" @bind:event="oninput" />
<p>@text</p>

@code {
    string text;
}

구성 요소는 해당 매개 변수에 대한 데이터 바인딩을 지원할 수도 있습니다. 데이터 바인딩에 대해 바인딩 가능 매개 변수와 동일한 이름을 사용하여 이벤트 콜백 매개 변수를 정의합니다. “Changed” 접미사가 이름에 추가됩니다.

PasswordBox.razor

Password: <input
    value="@Password"
    @oninput="OnPasswordChanged"
    type="@(showPassword ? "text" : "password")" />

<label><input type="checkbox" @bind="showPassword" />Show password</label>

@code {
    private bool showPassword;

    [Parameter]
    public string Password { get; set; }

    [Parameter]
    public EventCallback<string> PasswordChanged { get; set; }

    private Task OnPasswordChanged(ChangeEventArgs e)
    {
        Password = e.Value.ToString();
        return PasswordChanged.InvokeAsync(Password);
    }
}

데이터 바인딩을 기본 UI 요소에 연결하려면 값을 설정하고 @bind 특성을 사용하는 대신 UI 요소에서 직접 이벤트를 처리합니다.

구성 요소 매개 변수에 바인딩하려면 @bind-{Parameter} 특성을 사용하여 바인딩할 매개 변수를 지정합니다.

<PasswordBox @bind-Password="password" />

@code {
    string password;
}

상태 변경

구성 요소의 상태가 일반 UI 이벤트 또는 이벤트 콜백 외부에서 변경된 경우 구성 요소는 다시 렌더링해야 한다는 신호를 수동으로 보내야 합니다. 구성 요소 상태가 변경되었다는 신호를 보내려면 구성 요소에서 StateHasChanged 메서드를 호출합니다.

아래 예제에서 구성 요소는 앱의 다른 파트에서 업데이트할 수 있는 AppState 서비스의 메시지를 표시합니다. 구성 요소는 메시지가 업데이트될 때마다 구성 요소가 렌더링되도록 해당 StateHasChanged 메서드를 AppState.OnChange 이벤트에 등록합니다.

public class AppState
{
    public string Message { get; }

    // Lets components receive change notifications
    public event Action OnChange;

    public void UpdateMessage(string message)
    {
        Message = message;
        NotifyStateChanged();
    }

    private void NotifyStateChanged() => OnChange?.Invoke();
}
@inject AppState AppState

<p>App message: @AppState.Message</p>

@code {
    protected override void OnInitialized()
    {
        AppState.OnChange += StateHasChanged
    }
}

구성 요소 수명 주기

ASP.NET Web Forms 프레임워크에는 모듈, 페이지, 컨트롤의 잘 정의된 수명 주기 메서드가 있습니다. 예를 들어 다음 컨트롤은 Init, Load, UnLoad 수명 주기 이벤트의 이벤트 처리기를 구현합니다.

Counter.ascx.cs

public partial class Counter : System.Web.UI.UserControl
{
    protected void Page_Init(object sender, EventArgs e) { ... }
    protected void Page_Load(object sender, EventArgs e) { ... }
    protected void Page_UnLoad(object sender, EventArgs e) { ... }
}

Razor 구성 요소에는 잘 정의된 수명 주기도 있습니다. 구성 요소의 수명 주기를 사용하여 구성 요소 상태를 초기화하고 고급 구성 요소 동작을 구현할 수 있습니다.

모든 Blazor의 구성 요소 수명 주기 메서드에는 동기 버전과 비동기 버전이 둘 다 있습니다. 구성 요소 렌더링은 동기적입니다. 비동기 논리는 구성 요소 렌더링의 일부로 실행할 수 없습니다. 모든 비동기 논리는 async 수명 주기 메서드의 일부로 실행되어야 합니다.

OnInitialized

OnInitializedOnInitializedAsync 메서드는 구성 요소를 초기화하는 데 사용됩니다. 구성 요소는 일반적으로 처음 렌더링된 후에 초기화됩니다. 구성 요소는 초기화된 후 최종적으로 삭제되기 전에 여러 번 렌더링될 수 있습니다. OnInitialized 메서드는 ASP.NET Web Forms 페이지 및 컨트롤의 Page_Load 이벤트와 비슷합니다.

protected override void OnInitialized() { ... }
protected override async Task OnInitializedAsync() { await ... }

OnParametersSet

OnParametersSetOnParametersSetAsync 메서드는 구성 요소가 부모의 매개 변수를 수신했고 값이 속성에 할당될 때 호출됩니다. 이 메서드는 구성 요소 초기화 후 및 ‘구성 요소가 렌더링될 때마다’ 실행됩니다.

protected override void OnParametersSet() { ... }
protected override async Task OnParametersSetAsync() { await ... }

OnAfterRender

OnAfterRenderOnAfterRenderAsync 메서드는 구성 요소 렌더링을 완료한 후에 호출됩니다. 이때 요소 및 구성 요소 참조가 채워집니다(아래에서 해당 개념 참조). 이제 브라우저와 상호 작용할 수 있습니다. DOM 및 JavaScript 실행과 상호 작용을 안전하게 수행할 수 있습니다.

protected override void OnAfterRender(bool firstRender)
{
    if (firstRender)
    {
        ...
    }
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        await ...
    }
}

OnAfterRenderOnAfterRenderAsync는 ‘서버에서 미리 렌더링될 때 호출되지 않습니다’.

firstRender 매개 변수는 구성 요소가 처음 렌더링될 때 true이고 이외에는 해당 값이 false입니다.

IDisposable

Razor 구성 요소는 UI에서 구성 요소가 제거될 때 리소스를 삭제하는 IDisposable을 구현할 수 있습니다. Razor 구성 요소는 IDispose 지시문을 사용하여 @implements를 구현할 수 있습니다.

@using System
@implements IDisposable

...

@code {
    public void Dispose()
    {
        ...
    }
}

구성 요소 참조 캡처

ASP.NET Web Forms에서는 일반적으로 컨트롤 인스턴스의 ID를 참조하여 코드에서 직접 컨트롤 인스턴스를 조작합니다. 거의 일반적이지는 않지만 Blazor에서 구성 요소에 대한 참조를 캡처 및 조작할 수도 있습니다.

Blazor에서 구성 요소 참조를 캡처하려면 @ref 지시문 특성을 사용합니다. 특성 값은 참조된 구성 요소와 형식이 동일한 설정 가능한 필드의 이름과 일치해야 합니다.

<MyLoginDialog @ref="loginDialog" ... />

@code {
    MyLoginDialog loginDialog = default!;

    void OnSomething()
    {
        loginDialog.Show();
    }
}

부모 구성 요소가 렌더링되면 필드가 자식 구성 요소 인스턴스로 채워집니다. 그런 다음, 구성 요소 인스턴스에서 메서드를 호출하거나 구성 요소 인스턴스를 조작할 수 있습니다.

구성 요소 참조를 사용하여 구성 요소 상태를 직접 조작하지 않는 것이 좋습니다. 이렇게 하면 구성 요소가 올바른 시간에 자동으로 렌더링되지 않습니다.

요소 참조 캡처

Razor 구성 요소는 요소에 대한 참조를 캡처할 수 있습니다. ASP.NET Web Forms의 HTML 서버 컨트롤과 달리 Blazor의 요소 참조를 사용하여 DOM을 직접 조작할 수 없습니다. Blazor는 DOM diff 알고리즘을 사용하여 대부분의 DOM 상호 작용을 처리합니다. Blazor의 캡처된 요소 참조는 불투명합니다. 그러나 JavaScript interop 호출에서 특정 요소 참조를 전달하는 데 사용됩니다. JavaScript interop에 관한 자세한 내용은 ASP.NET Core Blazor JavaScript interop을 참조하세요.

템플릿 기반 구성 요소

ASP.NET Web Forms에서 ‘템플릿 기반 컨트롤’을 만들 수 있습니다. 개발자는 템플릿 기반 컨트롤을 사용하여 컨테이너 컨트롤을 렌더링하는 데 사용되는 HTML 부분을 지정할 수 있습니다. 템플릿 기반 서버 컨트롤을 빌드하는 메커니즘은 복잡하지만 사용자 지정 가능한 방식으로 데이터를 렌더링하는 강력한 시나리오를 가능하게 합니다. 템플릿 기반 컨트롤의 예로는 RepeaterDataList가 있습니다.

RenderFragment 또는 RenderFragment<T> 형식의 구성 요소 매개 변수를 정의하여 Razor 구성 요소를 템플릿으로 만들 수도 있습니다. RenderFragment는 구성 요소에서 렌더링할 수 있는 Razor 태그의 청크를 나타냅니다. RenderFragment<T>는 렌더링 조각이 렌더링될 때 지정할 수 있는 매개 변수를 사용하는 Razor 태그의 청크입니다.

자식 콘텐츠

Razor 구성 요소는 자식 콘텐츠를 RenderFragment로 캡처하고 해당 콘텐츠를 구성 요소 렌더링의 일부로 렌더링할 수 있습니다. 자식 콘텐츠를 캡처하려면 RenderFragment 형식의 구성 요소 매개 변수를 정의하고 이름을 ChildContent로 지정합니다.

ChildContentComponent.razor

<h1>Component with child content</h1>

<div>@ChildContent</div>

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

그러면 부모 구성 요소가 일반 Razor 구문을 사용하여 자식 콘텐츠를 제공할 수 있습니다.

<ChildContentComponent>
    <ChildContent>
        <p>The time is @DateTime.Now</p>
    </ChildContent>
</ChildContentComponent>

템플릿 매개 변수

또한 템플릿 기반 Razor 구성 요소는 RenderFragment 또는 RenderFragment<T> 형식의 여러 구성 요소 매개 변수를 정의할 수 있습니다. RenderFragment<T>의 매개 변수는 호출될 때 지정할 수 있습니다. 구성 요소의 제네릭 형식 매개 변수를 지정하려면 @typeparam Razor 지시문을 사용합니다.

SimpleListView.razor

@typeparam TItem

@Heading

<ul>
@foreach (var item in Items)
{
    <li>@ItemTemplate(item)</li>
}
</ul>

@code {
    [Parameter]
    public RenderFragment Heading { get; set; }

    [Parameter]
    public RenderFragment<TItem> ItemTemplate { get; set; }

    [Parameter]
    public IEnumerable<TItem> Items { get; set; }
}

템플릿 기반 구성 요소를 사용하는 경우, 매개 변수 이름과 일치하는 자식 요소를 사용하여 템플릿 매개 변수를 지정할 수 있습니다. 요소로 전달되는 RenderFragment<T> 형식의 구성 요소 인수에는 context라는 암시적 매개 변수가 있습니다. 자식 요소에서 Context 특성을 사용하여 이 구현 매개 변수의 이름을 변경할 수 있습니다. 형식 매개 변수 이름과 일치하는 특성을 사용하여 제네릭 형식 매개 변수를 지정할 수 있습니다. 가능한 경우 형식 매개 변수가 유추됩니다.

<SimpleListView Items="messages" TItem="string">
    <Heading>
        <h1>My list</h1>
    </Heading>
    <ItemTemplate Context="message">
        <p>The message is: @message</p>
    </ItemTemplate>
</SimpleListView>

이 구성 요소의 출력은 다음과 같습니다.

<h1>My list</h1>
<ul>
    <li><p>The message is: message1</p></li>
    <li><p>The message is: message2</p></li>
<ul>

코드 숨김

Razor 구성 요소는 일반적으로 단일 .razor 파일로 작성됩니다. 그러나 코드 숨김 파일을 사용하여 코드와 태그를 분리할 수도 있습니다. 구성 요소 파일을 사용하려면 구성 요소 파일의 파일 이름과 일치하지만 .cs 확장명이 추가된 C# 파일(Counter.razor.cs)을 추가합니다. C# 파일을 사용하여 구성 요소의 기본 클래스를 정의합니다. 기본 클래스 이름을 원하는 대로 지정할 수 있지만, 일반적으로 구성 요소 클래스의 이름과 동일하지만 Base 확장명이 추가된 클래스 이름을 지정합니다(CounterBase). 구성 요소 기반 클래스도 ComponentBase에서 파생되어야 합니다. 그런 다음, Razor 구성 요소 파일에서 @inherits 지시문을 추가하여 구성 요소의 기본 클래스를 지정합니다(@inherits CounterBase).

Counter.razor

@inherits CounterBase

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button @onclick="IncrementCount">Click me</button>

Counter.razor.cs

public class CounterBase : ComponentBase
{
    protected int currentCount = 0;

    protected void IncrementCount()
    {
        currentCount++;
    }
}

기본 클래스에서 구성 요소 멤버의 표시 여부는 protected이거나 구성 요소 클래스에 표시되려면 public이어야 합니다.

추가 리소스

이전 항목이 Razor 구성 요소의 모든 측면을 완벽하게 처리하지는 않습니다. ASP.NET Core Razor 구성 요소를 만들고 사용하는 방법에 관한 자세한 내용은 Blazor 설명서를 참조하세요.