Skip to content

Latest commit

Β 

History

History
131 lines (93 loc) Β· 7.86 KB

File metadata and controls

131 lines (93 loc) Β· 7.86 KB

μžλ°”μŠ€ν¬λ¦½νŠΈ μƒν˜Έμš΄μš©μ„±(JavaScript interop)

이제 ν”Όμž κ°€κ²Œ μ‚¬μš©μžλŠ” μ£Όλ¬Έ μƒνƒœλ₯Ό μ‹€μ‹œκ°„μœΌλ‘œ 좔적할 수 μžˆμŠ΅λ‹ˆλ‹€. 이 μ„Έμ…˜μ—μ„œλŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ μƒν˜Έμš΄μš©μ„±μ„ μ‚¬μš©ν•˜μ—¬ "λ‚΄ ν”ΌμžλŠ” μ–΄λ”” μžˆμ§€?!?"λΌλŠ” 였래된 μ§ˆλ¬Έμ— λ‹΅ν•˜λŠ” μ£Όλ¬Έ μƒνƒœ νŽ˜μ΄μ§€μ— μ‹€μ‹œκ°„ 지도λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.

지도 μ»΄ν¬λ„ŒνŠΈ

ComponentsLibrary ν”„λ‘œμ νŠΈμ—λŠ” 마컀 μ„ΈνŠΈμ˜ μœ„μΉ˜λ₯Ό ν‘œμ‹œν•˜κ³  μ‹œκ°„ 경과에 λ”°λ₯Έ μ›€μ§μž„μ— μ• λ‹ˆλ©”μ΄μ…˜μ„ μœ„ν•΄ 이미 μž‘μ„±λœ Map μ»΄ν¬λ„ŒνŠΈκ°€ ν¬ν•¨λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. 이 μ»΄ν¬λ„ŒνŠΈλ₯Ό μ‚¬μš©ν•˜μ—¬ μ‚¬μš©μžμ˜ ν”Όμž 주문이 배달 λ˜λŠ” μœ„μΉ˜λ₯Ό ν‘œμ‹œν•˜μ§€λ§Œ Map μ»΄ν¬λ„ŒνŠΈκ°€ μ–΄λ–»κ²Œ κ΅¬ν˜„λ˜λŠ”μ§€ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

Map.razor νŒŒμΌμ„ μ—΄κ³  μ•„λž˜ μ½”λ“œλ₯Ό μ‚΄νŽ΄λ³΄μ„Έμš”.

@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime

<div id="@elementId" style="height: 100%; width: 100%;"></div>

@code {
    string elementId = $"map-{Guid.NewGuid().ToString("D")}";

    [Parameter] double Zoom { get; set; }
    [Parameter] List<Marker> Markers { get; set; }

    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        await JSRuntime.InvokeVoidAsync(
            "deliveryMap.showOrUpdate",
            elementId,
            Markers);
    }
}

Map ꡬ성 μš”μ†ŒλŠ” 쒅속성 μ£Όμž…μ„ μ‚¬μš©ν•˜μ—¬ IJSRuntime μΈμŠ€ν„΄μŠ€λ₯Ό κ°€μ Έμ˜΅λ‹ˆλ‹€. 이 μ„œλΉ„μŠ€λ₯Ό μ‚¬μš©ν•˜λ©΄ InvokeVoidAsync λ˜λŠ” InvokeAsync<TResult> λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ—¬ λΈŒλΌμš°μ € API λ˜λŠ” κΈ°μ‘΄ JavaScript λΌμ΄λΈŒλŸ¬λ¦¬μ— λŒ€ν•œ JavaScript ν˜ΈμΆœμ„ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이 λ©”μ†Œλ“œμ˜ 첫 번째 λ§€κ°œλ³€μˆ˜λŠ” 루트 window 객체λ₯Ό κΈ°μ€€μœΌλ‘œ ν˜ΈμΆœν•  JavaScript ν•¨μˆ˜μ˜ 경둜λ₯Ό μ§€μ •ν•©λ‹ˆλ‹€. λ‚˜λ¨Έμ§€ λ§€κ°œλ³€μˆ˜λŠ” JavaScript ν•¨μˆ˜μ— 전달할 μΈμˆ˜μž…λ‹ˆλ‹€. μΈμˆ˜λŠ” JavaScript둜 처리될 수 μžˆλ„λ‘ JSON으둜 μ§λ ¬ν™”λ©λ‹ˆλ‹€.

Map μ»΄ν¬λ„ŒνŠΈλŠ” λ¨Όμ € μ§€λ„μ˜ 고유 ID둜 divλ₯Ό λ Œλ”λ§ν•œ λ‹€μŒ deliveryMap.showOrUpdate ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ μ§€μ •λœ λ§ˆμ»€κ°€ Map μ»΄ν¬λ„ŒνŠΈμ— 전달해 지도에 ν‘œμ‹œν•©λ‹ˆλ‹€. 이 μž‘μ—…μ€ OnAfterRenderAsync ν•¨μˆ˜μ—μ„œ μ™„λ£Œλ˜μ–΄ μ»΄ν¬λ„ŒνŠΈ 수λͺ… μ£ΌκΈ° μ΄λ²€νŠΈμ—μ„œ μˆ˜ν–‰μ΄ μ™„λ£Œλ©λ‹ˆλ‹€. deliveryMap.showOrUpdate ν•¨μˆ˜λŠ” wwwroot/deliveryMap.js νŒŒμΌμ— μ •μ˜λ˜μ–΄ 있으며 leaflet.jsκ³Ό OpenStreetMap을 μ΄μš©ν•˜μ—¬ 지도에 ν‘œμ‹œν•©λ‹ˆλ‹€. 이 μ½”λ“œμ˜ μž‘λ™ 방식에 λŒ€ν•œ μ„ΈλΆ€ 사항은 μ‹€μ œλ‘œ μ€‘μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ€‘μš”ν•œ 점은 λͺ¨λ“  JavaScript ν•¨μˆ˜λ₯Ό 이런 λ°©μ‹μœΌλ‘œ ν˜ΈμΆœν•  수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

이런 νŒŒμΌμ€ μ–΄λ–»κ²Œ λΈ”λ ˆμ΄μ € 앱에 μΆ”κ°€ν•˜λ‚˜μš”? λΈ”λ ˆμ΄μ € 라이브러리 ν”„λ‘œμ νŠΈ(Sdk="Microsoft.NET.Sdk.Razor")λ₯Ό μ‚¬μš©ν•˜λ©΄ wwwroot/ 폴더에 μžˆλŠ” λͺ¨λ“  νŒŒμΌμ€ λΌμ΄λΈŒλŸ¬λ¦¬μ™€ ν•¨κ»˜ λ²ˆλ“€λ‘œ μ œκ³΅λ©λ‹ˆλ‹€. μ„œλ²„ ν”„λ‘œμ νŠΈλŠ” 정적 파일 미듀웨어λ₯Ό μ‚¬μš©ν•˜μ—¬ μ΄λŸ¬ν•œ νŒŒμΌμ„ μžλ™μœΌλ‘œ μ œκ³΅ν•©λ‹ˆλ‹€.

λΈ”λ ˆμ΄μ € ν΄λΌμ΄μ–ΈνŠΈ 앱을 ν˜ΈμŠ€νŒ…ν•˜λŠ” νŽ˜μ΄μ§€μ— μ›ν•˜λŠ” 파일(이 경우 .js 및 .css)을 ν¬ν•¨μ‹œν‚€λŠ” 링크가 λ§ˆμ§€λ§‰μ— μžˆμŠ΅λ‹ˆλ‹€. index.htmlμ—λŠ” _content/BlazingPizza.ComponentsLibrary/localStorage.js와 같은 μƒλŒ€ URIλ₯Ό μ‚¬μš©ν•˜μ—¬ μ΄λŸ¬ν•œ 파일이 ν¬ν•¨λ©λ‹ˆλ‹€. μ΄λŠ” λΈ”λ ˆμ΄μ € 클래슀 라이브러리(_content/<라이브러리 이름>/<파일 경둜>)와 ν•¨κ»˜ λ²ˆλ“€λ‘œ μ œκ³΅λ˜λŠ” μ°Έμ‘° 파일의 일반적인 νŒ¨ν„΄μž…λ‹ˆλ‹€.


Map에 μž…λ ₯을 μ‹œμž‘ν•˜λ©΄ νŽΈμ§‘κΈ°μ—μ„œ μ™„μ„± κΈ°λŠ₯을 μ œκ³΅ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” 것을 μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” μš”μ†Œμ™€ μ»΄ν¬λ„ŒνŠΈ κ°„μ˜ 바인딩이 C#의 λ„€μž„μŠ€νŽ˜μ΄μŠ€ 바인딩 κ·œμΉ™μ— μ˜ν•΄ μ œμ–΄λ˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. Map ꡬ성 μš”μ†ŒλŠ” BlazingPizza.ComponentsLibrary.Map λ„€μž„μŠ€νŽ˜μ΄μŠ€μ— μ •μ˜λ˜μ–΄ μžˆμ§€λ§Œ 이에 λŒ€ν•œ @using이 μ—†μŠ΅λ‹ˆλ‹€.

이 λ„€μž„μŠ€νŽ˜μ΄μŠ€μ— λŒ€ν•œ @using을 루트 _Imports.razor에 μΆ”κ°€ν•˜μ—¬ 이 μ»΄ν¬λ„ŒνŠΈ λ²”μœ„λ‘œ κ°€μ Έμ˜΅λ‹ˆλ‹€.

@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.JSInterop
@using BlazingPizza.Client
@using BlazingPizza.Client.Shared
@using BlazingPizza.ComponentsLibrary
@using BlazingPizza.ComponentsLibrary.Map

track-order-details div λ°”λ‘œ μ•„λž˜μ— λ‹€μŒμ„ μΆ”κ°€ν•˜μ—¬ OrderDetails νŽ˜μ΄μ§€μ— Map ꡬ성 μš”μ†Œλ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.

<div class="track-order-map">
    <Map Zoom="13" Markers="orderWithStatus.MapMarkers" />
</div>

μ΄μ „μ—λŠ” μ»΄ν¬λ„ŒνŠΈμ— @using을 μΆ”κ°€ν•  ν•„μš”κ°€ μ—†μ—ˆλ˜ μ΄μœ λŠ” 루트 _Imports.razor에 μš°λ¦¬κ°€ μž‘μ„±ν•œ μž¬μ‚¬μš© κ°€λŠ₯ν•œ μ»΄ν¬λ„ŒνŠΈμ™€ μΌμΉ˜ν•˜λŠ” @using BlazingPizza.Sharedκ°€ 이미 ν¬ν•¨λ˜μ–΄ 있기 λ•Œλ¬Έμž…λ‹ˆλ‹€.

OrderDetails μ»΄ν¬λ„ŒνŠΈκ°€ μ£Όλ¬Έ μƒνƒœ μ—…λ°μ΄νŠΈλ₯Ό μœ„ν•΄ 폴링할 λ•Œ 지도에 ν”Όμžμ˜ μ΅œμ‹  μœ„μΉ˜κ°€ 반영된 λ§ˆμ»€κ°€ λ°˜μ˜λ©λ‹ˆλ‹€.

Real-time pizza map

ν”Όμž μ‚­μ œ 확인 λ©”μ‹œμ§€ μΆ”κ°€

Map μ»΄ν¬λ„ŒνŠΈμ— λŒ€ν•œ μžλ°”μŠ€ν¬λ¦½νŠΈ μƒν˜Έμš΄μš©μ„± μ½”λ“œλŠ” μ œκ³΅λ˜μ—ˆμŠ΅λ‹ˆλ‹€. λ‹€μŒμœΌλ‘œλŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ μƒν˜Έμš΄μš©μ„± μ½”λ“œλ₯Ό μΆ”κ°€ν•΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

μ‚¬μš©μžκ°€ μ‹€μˆ˜λ‘œ μ£Όλ¬Έμ—μ„œ ν”Όμžλ₯Ό μ‚­μ œν•˜κ³  κ²°κ΅­ ν”Όμžλ₯Ό κ΅¬λ§€ν•˜μ§€ μ•Šκ²Œ λœλ‹€λ©΄ μ•ˆνƒ€κΉŒμš΄ 일이 될 κ²ƒμž…λ‹ˆλ‹€. μ‚¬μš©μžκ°€ ν”Όμžλ₯Ό μ‚­μ œν•˜λ €κ³  ν•  λ•Œ 확인 λ©”μ‹œμ§€λ₯Ό μΆ”κ°€ν•΄ λ³΄κ² μŠ΅λ‹ˆλ‹€. μžλ°”μŠ€ν¬λ¦½νŠΈ μƒν˜Έμš΄μš©μ„±μ„ μ‚¬μš©ν•˜μ—¬ 확인 ν”„λ‘¬ν”„νŠΈλ₯Ό ν‘œμ‹œν•˜κ² μŠ΅λ‹ˆλ‹€.

IJSRuntime의 Confirm ν™•μž₯ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ ν΄λΌμ΄μ–ΈνŠΈ ν”„λ‘œμ νŠΈμ— 정적 JSRuntimeExtensions 클래슀λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€. λ‚΄μž₯된 JavaScript confirm ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ €λ©΄ Confirm λ©”μ†Œλ“œλ₯Ό κ΅¬ν˜„ν•˜μ‹­μ‹œμ˜€.

public static class JSRuntimeExtensions
{
    public static ValueTask<bool> Confirm(this IJSRuntime jsRuntime, string message)
    {
        return jsRuntime.InvokeAsync<bool>("confirm", message);
    }
}

μžλ°”μŠ€ν¬λ¦½νŠΈ μƒν˜Έμš΄μš©μ„± ν˜ΈμΆœμ„ μˆ˜ν–‰ν•˜λŠ” 데 μ‚¬μš©ν•  수 μžˆλ„λ‘ Index ꡬ성 μš”μ†Œμ— IJSRuntime μ„œλΉ„μŠ€λ₯Ό μ‚½μž…ν•©λ‹ˆλ‹€.

@page "/"
@inject HttpClient HttpClient
@inject OrderState OrderState
@inject NavigationManager NavigationManager
@inject IJSRuntime JS

μ‚¬μš©μžκ°€ μ‹€μ œλ‘œ μ£Όλ¬Έμ—μ„œ ν”Όμžλ₯Ό μ œκ±°ν•˜κΈ°λ₯Ό μ›ν•˜λŠ”μ§€ ν™•μΈν•˜κΈ° μœ„ν•΄ Confirm λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” Index ꡬ성 μš”μ†Œμ— 비동기 RemovePizza λ©”μ„œλ“œλ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.

async Task RemovePizza(Pizza configuredPizza)
{
    if (await JS.Confirm($"Remove {configuredPizza.Special.Name} pizza from the order?"))
    {
        OrderState.RemoveConfiguredPizza(configuredPizza);
    }
}

Index μ»΄ν¬λ„ŒνŠΈμ—μ„œ ConfiguredPizzaItems에 λŒ€ν•œ 이벀트 ν•Έλ“€λŸ¬λ₯Ό μˆ˜μ •ν•˜μ—¬ μƒˆλ‘œμš΄ RemovePizza λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€.

@foreach (var configuredPizza in OrderState.Order.Pizzas)
{
    <ConfiguredPizzaItem Pizza="configuredPizza" OnRemoved="@(() => RemovePizza(configuredPizza))" />
}

앱을 μ‹€ν–‰ν•˜κ³  μ£Όλ¬Έμ—μ„œ ν”Όμžλ₯Ό μ‚­μ œν•΄ λ³΄μ„Έμš”.

Confirm pizza removal

ConfiguredPizzaItem.OnRemovedλ₯Ό λΉ„λ™κΈ°λ‘œ μ‹€ν–‰ν•˜κΈ° μœ„ν•΄ λ©”μ„œλ“œ μ‹œκ·Έλ‹ˆμ²˜λ₯Ό μˆ˜μ •ν•΄μ•Ό ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. EventCallback의 λ‹€λ₯Έ 특수 μ†μ„±μœΌλ‘œ 동기, 비동기 이벀트 ν•Έλ“€λŸ¬λ₯Ό λͺ¨λ‘ μ§€μ›ν•©λ‹ˆλ‹€.

λ‹€μŒ μ„Έμ…˜ - ν…œν”Œλ¦Ώ μ»΄ν¬λ„ŒνŠΈ

원문 읽기 - Javascript interop