繁体   English   中英

剃刀组件中的C#StateHasChanged()不强制 <video> 标签以加载/更改mp4播放,仅使用javascript似乎有效

[英]C# StateHasChanged() in a razor component does not force <video> tag to load/change the mp4 playing, only using javascript seems to work

我正在尝试使用服务器端的blazor。 我试图在剃刀组件的标签中设置多个按钮来设置/更改播放的.mp4文件。 我发现完成这项工作的唯一方法是从剃刀组件中的OnParametersSet()通过IJSRuntime:InvokeVoidAsync()调用javascript函数。 javascript函数位于_Host.cshtml中。 对于应该是一个简单问题的解决方案,这似乎是一个非常丑陋的解决方案。

我尝试在OnClick按钮函数中使用StateHasChanged()。 当我查看chrome中的html渲染时,h1-header标签和源src =“ NewFile”显示为更新,并且当单击按钮但未加载新视频时,h1标签在页面上正确更改。 我的猜测是,这与在其自己的线程上播放的视频有关,或者视频标签本身没有变化。 我只是不明白如何从razor / c#做到这一点。

由于生成错误,因此将Javascript代码添加到了文件:_Html.cshtml

  <script>
        function loadVideo (strNewVideo)
        {
            document.getElementById('videoSourceId').src = strNewVideo;
            document.getElementById("videoTagId").load();
        }
    </script>

播放视频的简单组件... File:VideoPlayer.razor

@inject IJSRuntime theJavaScriptEngine;

<div class="align-content-center">
    <h1>@this.m_strRenderMe</h1>
    <video id="videoTagId" autoplay width="1080" height="720">
        <source id="videoSourceId" src=@this.m_strRenderMe type="video/mp4" />
    </video>
</div>

@code {
    ElementReference theVideoTag;

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

    private string m_strRenderMe;

    protected override void OnParametersSet()
    {
        this.m_strRenderMe = this.strVideoFilePath;

        theJavaScriptEngine.InvokeVoidAsync("loadVideo", this.m_strRenderMe);

        this.StateHasChanged();
    }
}

剃刀页面上方带有组件,文件中包含4个按钮:Counter.razor

@page "/counter"

@using UseBlazorToReadPowerPoint.Classes

@inject CPersistantAppState  thePersistantAppState


<VideoPlayer strVideoFilePath=@thePersistantAppState.m_strVideoPath></VideoPlayer>

<button class="btn btn-primary" @onclick="PlayVideo_1">Video 1</button>
<button class="btn btn-primary" @onclick="PlayVideo_2">Video 2</button>
<button class="btn btn-primary" @onclick="PlayVideo_3">Video 3</button>
<button class="btn btn-primary" @onclick="PlayVideo_4">Video 4</button>

@code {

    void PlayVideo_1()
        {
        thePersistantAppState.m_strVideoPath = "videos/Video-1.mp4";
        }

    void PlayVideo_2()
    {
        thePersistantAppState.m_strVideoPath = "videos/Video-2.mp4";
    }

    void PlayVideo_3()
    {
        thePersistantAppState.m_strVideoPath = "videos/Video-3.mp4";
    }

    void PlayVideo_4()
    {
        thePersistantAppState.m_strVideoPath = "videos/Video-4.mp4";
    }

}

保留所选文件名。 文件:CPersistantAppState.cs

namespace UseBlazorToReadPowerPoint.Classes
{
    public class CPersistantAppState
    {
        public string m_strVideoPath;
    }
}

列出的代码有效。 我只是不知道如何在没有JavaScript调用的情况下使这项工作有效。 似乎必须有一种更清洁的方式来执行此操作。

问题不StateHasChangeg() ,而是关于html的Video标签

通常,仅当您通过更改元素的src属性或添加或删除嵌套在media元素自身中的元素对可用于media元素的源集进行了动态更改时,此方法才有用。 load()将重置元素并重新扫描可用的源,从而使更改生效

这意味着更改src属性后必须执行调用load 您目前无法从blazor调用load ,这意味着您应该通过IJSRuntime调用它:

开拓者代码

<div class="align-content-center">
    <h1>@m_strRenderMe[currentVideo]</h1>
    <button @onclick="ChangeVideo">Change video</button>
    <video id="videoTagId" autoplay width="1080" height="720">
        <source id="videoSourceId" src="@m_strRenderMe[currentVideo]" type="video/mp4" />
    </video>
</div>

@code
{
    int currentVideo = 0;
    string[] m_strRenderMe = new string[] {
        "https://.../videoplayback-1.mp4",
        "https://.../videoplayback-2.mp4"
    };
    protected void ChangeVideo()
    {
        currentVideo = (currentVideo + 1) % 2;
        theJavaScriptEngine.InvokeVoidAsync("loadVideo");
    }
}

JS代码

<script>
    function loadVideo ()
    {
        document.getElementById("videoTagId").load();
    }
</script>

BlazorFiddle检查一下。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM