单击Blazor中的顶部导航链接时,滚动到页面的指定部分

时间:2019-03-15 16:19:38

标签: c# html css blazor

如何在Blazor中使已加载页面的简单“跳转到”部分?像这样的HTML:

var obj = {file: "file.doc", myData: "['dat1','dat2']"}
//turn myData into an array.
var arr = obj.myData.split("["); // ["", "'dat1','dat2']"]
//remove the first (empty string) element.
arr.splice(0, 1); // ["'dat1','dat2']"]
//convert the other element (string) into an array of 2 
  elements.
var newArr = arr[0].split(","); //["'dat1'", "'dat2']"]
//declare an empty array
var finalArr = [];
//loop over newArr  array, and push the result of cutting the 
  string from index 1 to 4
for (const element of newArr ) {
finalArr.push(element.substring(1, 4));
}
//reassign the value of myData property of obj object.
obj.myData = finalArr;
console.log(obj.myData); //["dat1", "dat2"]

理想情况下,我还希望其向下平滑滚动至此部分。以为我会尝试使用CSS来解决这个问题,但也许不可能吗?

3 个答案:

答案 0 :(得分:3)

您需要的是Blazor的哈希路由功能。但是,可惜的是,还没有这样的功能。我建议您使用JSIterop执行此任务:创建执行导航的JavaScript,然后将ElementRef对象传递给它。

希望这对您有帮助...

编辑:以下内容是我在Github中找到的最佳解决方法的改编...

通常,当您单击链接进行联系时,您将被重定向到路线http://localhost:5000/mypage#contact,但将位于页面顶部。路由的片段不用于选择特定的HTML元素。

当前的解决方法是编写用于解释URL的显式代码。在上面的示例中,我们可以使用一些JavaScript,然后从Blazor代码中调用它:

mypage.cshtml:

         @page "/mypage"
    @inject Microsoft.AspNetCore.Components.Services.IUriHelper UriHelper

    <nav>

        <a href="#contact">contact</a>


    </nav>


    <section>
        <h2 id="contact">contact</h2>

    </section>


@functions {
    protected override void OnInit()
    {
        NavigateToElement();
        UriHelper.OnLocationChanged += OnLocationChanges;
    }

    private void OnLocationChanges(object sender, string location) => NavigateToElement();

    private void NavigateToElement()
    {
        var url = UriHelper.GetAbsoluteUri();
        var fragment = new Uri(url).Fragment;

        if(string.IsNullOrEmpty(fragment))
        {
            return;
        }

        var elementId = fragment.StartsWith("#") ? fragment.Substring(1) : fragment;

        if(string.IsNullOrEmpty(elementId))
        {
            return;
        }

        ScrollToElementId(elementId);
    }

    private static bool ScrollToElementId(string elementId)
    {
        return JSRuntime.Current.InvokeAsync<bool>("scrollToElementId", elementId).GetAwaiter().GetResult();
    }
}

index.html:

<script>
        window.scrollToElementId = (elementId) => {
            console.info('scrolling to element', elementId);
            var element = document.getElementById(elementId);
            if(!element)
            {
                console.warn('element was not found', elementId);
                return false;
            }
            element.scrollIntoView();
            return true;
        }
</script>

注意:如果使用的是Blazor版本.9.0,则应注入IJSRuntime       请让我知道该解决方案是否适合您...

答案 1 :(得分:2)

我使用了Arron Hudon的答案,但仍然没有用。但是,在玩转之后,我意识到它不适用于锚元素 var object={"statusCode": 200, "headers": {}, "body": "{\"statusColor\": {\"abc1\": \"green\", \"abc2\": \"red\", \"bcd11\": \"red\", \"bcd2\": \"green\", \"cde1\": \"green\", \"cde2\": \"red\", \"efg1\": \"red\", \"efg2\": \"red\", \"efg3\": \"red\"}, \"time\": {\"abc\": \"2020-02-03 11:41:40\", \"bcd\": \"2020-02-03 11:41:40\", \"cde\": \"2020-02-03 11:41:40\", \"efg\": \"2020-02-03 11:41:40\"}}"} //Iam trying to get the seperate dict object for statusColor and time as below var dict={} dict=object console.log("Status color is", dict.body['statusColor']) #Out put is 'undefined' 。显然,Blazor和其他spa框架在同一页面上遇到的问题跳到了 anchors 。为了解决这个问题,我不得不使用一个段落元素(段落也可以工作):<a id='star_wars'>Place to jump to</a>

使用引导程序的示例:

<p id='star_wars'>Some paragraph<p>

注意,我使用引导程序的<button class="btn btn-link" onclick="document.getElementById('star_wars').scrollIntoView({behavior:'smooth'})">Star Wars</button> ... lots of other text <p id="star_wars">Star Wars is an American epic...</p> 类使按钮看起来像超链接。

答案 2 :(得分:0)

与Issac的答案相同,但需要更改一些代码。

我发现主要问题是您需要使其异步。 @johajan

@inject IJSRuntime JSRuntime

...

@functions {
protected override async Task OnInitAsync()
{
    await base.OnInitAsync();
    //NavigateToElement();
    UriHelper.OnLocationChanged += OnLocationChanges;
}

private async Task OnLocationChanges(object sender, string location) => await NavigateToElement();

private async Task NavigateToElement()
{
    var url = UriHelper.GetAbsoluteUri();
    var fragment = new Uri(url).Fragment;

    if(string.IsNullOrEmpty(fragment))
    {
        return;
    }

    var elementId = fragment.StartsWith("#") ? fragment.Substring(1) : fragment;

    if(string.IsNullOrEmpty(elementId))
    {
        return;
    }

    await ScrollToElementId(elementId);
}

private Task<bool> ScrollToElementId(string elementId)
{
    return JSRuntime.InvokeAsync<bool>("scrollToElementId", elementId);
}

}