Javascript событие клика не работает в клиентском приложении Blazor - PullRequest
1 голос
/ 04 февраля 2020

Я новичок в Blazor и создал довольно простое приложение для веб-сборки. Я хочу ссылку href на go, чтобы разделить страницу вниз, когда я нажимаю на нее, но событие нажатия Javascript не будет работать. На странице Index.razor JsRuntime.InvokeVoidAsync("clicker") работает, а alert("In clicker") происходит при загрузке страницы, но нажатие / ссылка на go div "intro" не будет работать ни ради любви, ни за деньги: - /

index. html

<!DOCTYPE html>
<html>
<head>
    <title>My Blazor App</title>
    <!--script type='text/javascript' src='./scripts/app.js'-->
</head>
<body>
    <app>Loading...</app>
    <script src="_framework/blazor.webassembly.js"></script>
    <script>
        function clicker() {
            alert("In clicker"); // this works
            document.getElementById('skip').onclick = function(e){
                alert("clicked"); // this works but the page still won't scroll to the "intro" div :(
            }
        }
        //clicker();
    </script>
</body>
</html>

Index.razor (раздел @code находится вверху страницы)

@page "/"
@code {
    [Inject]
    protected IJSRuntime JsRuntime { get; set; }

    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            JsRuntime.InvokeVoidAsync("clicker");
        }
    }
}

// This link won't go to the intro div when clicked :(
<a id="skip" class="skip" href="#intro">skip this bit</a>
...
<div id="intro" class="home">
...
</div>

Startup.cs

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
    }

    public void Configure(IComponentsApplicationBuilder app)
    {
        app.AddComponent<App>("app");
    }
}

Если бы кто-то мог пролить свет на это, это спасло бы мою неделю.

Ответы [ 2 ]

4 голосов
/ 05 февраля 2020

Здесь нет необходимости в JavaScript.

Если вы добавите указанную цель c к вашей разметке, она будет просто работать.

Вы можете использовать target = "_ top "чтобы избежать Blazor перехвата навигации.

<a class="skip" href="#intro" target="_top">skip this bit</a>
...
<div id="intro" class="home">
...
</div>

Обратите внимание, что target="_top" просто указывает браузеру перемещаться в пределах самого верхнего фрейма в окне, это не значит, что вы прокрутите к сверху!

2 голосов
/ 05 февраля 2020

Страница не будет прокручиваться до элемента, который вы указали в ссылке. Это связано с тем, как обрабатывается маршрутизация в Blazor и большинстве других приложений SPA. Простое решение заключается в том, что вы можете создать свой собственный компонент AnchorLink и использовать немного JavaScript interop magi c.

1.Создать AnchorLink.razor в Pages/Shared

@code {

    public AnchorLink()
    {
        this.Attributes = new Dictionary<string, object>();
    }

    private string targetId = null;
    private bool preventDefault = false;

    /// <summary>
    /// This parameter supports arbitrary attributes.
    /// </summary>
    /// <remarks>
    /// Any attribute specified on the component, which is not defined as a parameter, whill be added to this dictionary.
    /// It is then uses as the source for attributes rendered onto the resulting HTML element below in the markup section
    /// of this component.
    /// For details, refer to <see cref="https://docs.microsoft.com/en-us/aspnet/core/blazor/components#attribute-splatting-and-arbitrary-parameters"/>.
    /// </remarks>
    [Parameter(CaptureUnmatchedValues = true)]
    public IDictionary<string, object> Attributes { get; set; }

    /// <summary>
    /// Supports child content for the component.
    /// </summary>
    /// <see cref="https://docs.microsoft.com/en-us/aspnet/core/blazor/components#child-content"/>
    [Parameter]
    public RenderFragment ChildContent { get; set; }

    [Inject]
    protected IJSRuntime JsInterop { get; set; }


    protected override void OnParametersSet()
    {
        string href = null;
        if (this.Attributes.ContainsKey("href"))
        {
            // If the href attribute has been specified, we examine the value of it. If if starts with '#'
            // we assume the rest of the value contains the ID of the element the link points to.
            href = $"{this.Attributes["href"]}";
            if (href.StartsWith("#"))
            {
                // If the href contains an anchor link we don't want the default click action to occur, but
                // rather take care of the click in our own method.
                this.targetId = href.Substring(1);
                this.preventDefault = true;
            }
        }
        base.OnParametersSet();
    }

    private async Task AnchorOnClickAsync()
    {
        if (!string.IsNullOrEmpty(this.targetId))
        {
            // If the target ID has been specified, we know this is an anchor link that we need to scroll
            // to, so we call the JavaScript method to take care of this for us.
            await this.JsInterop.InvokeVoidAsync("anchorLink.scrollIntoView", this.targetId);
        }
    }

}

<a href="" @onclick="this.AnchorOnClickAsync" @onclick:stopPropagation="false" />
<a @attributes="this.Attributes" @onclick="this.AnchorOnClickAsync" @onclick:preventDefault="this.preventDefault">Hello @this.ChildContent</a>

2.Добавить js в wwwroot/Index.html

<script src="_framework/blazor.webassembly.js"></script>
<script>
    window.anchorLink = {
    scrollIntoView: function (elementId) {
        // This function is called from the AnchorLink component using JavaScript interop.
        // It will try to find an element using the ID given to the function, and scroll that
        // element into view, if an element is found.
        var elem = document.getElementById(elementId);
        if (elem) {
            elem.scrollIntoView();
            window.location.hash = elementId;
        }
    }
}
</script>

3. Index.razor

<AnchorLink class="skip" href="#intro">skip this bit</AnchorLink>

См. https://mikaberglund.com/2019/12/28/creating-anchor-links-in-blazor-applications/

...