Blazor 컴포넌트 클라이언트단 js 분리 및 경로해결 유틸리티 메서드 만들기

Blazor 에는 css및 js를 컴포넌트에 종속시킬수 있는 기능이 있습니다.

css 분리 기능은 예제가 풍부하고 잘 되어있는데,
자바스크립트는 Interop 외의 예제가 찾기가 힘들더군요…

단순 UI 컨트롤 혹은 css 관리를 위한 기능은 클라이언트 쪽에서 돌아가야 효율적이므로 직접 js를 불러오는 기능이 필요합니다.

또한 기능이 특정 컴포넌트에만 연관있는 js는 전역으로 오염되지 않도록 관리해야 용이하겠죠.

이에 예제 및 경로 해결해주는 확장메서드를 구현해봤습니다.

프로젝트 폴더 구조
image

MainLayout.razor

@inherits LayoutComponentBase

<div class="page">
    <main>
        <input type="button" value="test" onclick="test()" />
        <article class="content px-4">
            @Body
        </article>
    </main>
</div>

<div id="blazor-error-ui">
    An unhandled error has occurred.
    <a href="" class="reload">Reload</a>
    <a class="dismiss">🗙</a>
</div>

<script src="./Components/Layout/MainLayout.razor.js"></script>

wwwroot/Components/Layout/MainLayout.razor.js에 생성되므로 경로를 위처럼 설정해주시면 됩니다.

저는 경로가 하드코딩되는게 싫기때문에 자동으로 경로를 해결해주는 유틸리티 메서드도 만들었습니다.

아마 모든 상황을 핸들링하려면 수정해야할 수 있습니다.

ComponentHelper.cs

public static class ComponentHelper
{
    private static Dictionary<Type, string> Paths { get; } = [];
    public static string ResolveJsPath(this IComponent component)
    {
        if (Paths.TryGetValue(component.GetType(), out var path))
        {
            return path;
        }

        var componentType = component.GetType();
        var assembly = componentType.Assembly;
        char[] assemblyNameForReplace = [.. assembly.GetName().Name, '.'];
        var componentName = componentType.FullName!.TrimStart(assemblyNameForReplace);
        var componentPath = componentName.Replace('.', '/');
        var jsPath = $"./{componentPath}.razor.js";

        Paths[componentType] = jsPath;

        return jsPath;
    }
}

적용후 MainLayout.razor

<div class="page">
    <main>
        <input type="button" value="test" onclick="test()" />
        <article class="content px-4">
            @Body
        </article>
    </main>
</div>

<div id="blazor-error-ui">
    An unhandled error has occurred.
    <a href="" class="reload">Reload</a>
    <a class="dismiss">🗙</a>
</div>

<script src="@this.ResolveJsPath()"></script>

4 Likes

경로를 자동으로 찾을 수 있는 유틸리티 메서드는 자동으로 찾아주는 메서드는 매우 좋네요. capitalize도 지원한다면 많은 부분에서 쓰일 수 있을 것 같네요 :slight_smile:

하지만 전역 오염과는 거리가 먼 JS import 방식이라는 것은 말씀드리고 싶네요. Blazor에서 JS를 interop 방식 예제만 많은 것은 이 방식으로 하지 않는다면 거의 모두 전역오염이 되기 때문입니다. 제시해주신 방법으로 JS를 script tag를 통해서 import하게되면 JS 안의 변수와 함수가 전역에서 접근 가능해지고 top-level 코드들이 모두 실행되기 때문에 전역오염이 됩니다.

좋은 말씀 감사합니다. 전역 오염 설명이 약간 부적절했던것 같습니다.
추가적으로 설명드리자면 예시는 일반 js였지만, 스크립트를 모듈로 적용하면 말씀하신 문제는 어느정도 관리가 될 것 같습니다.

1 Like