为位于 Blazor 子菜单中的 DOM 元素调用 JS 互操作函数

Invoking JS Interop Function for DOM element located in submenu in Blazor

我正在尝试调用一个 JS 函数,该函数在用户单击 Blazor 中的 JS Interop 时创建一个模式。问题是,该函数正在对 Blazor 子菜单内的 DOM 元素使用 onclick 事件。当 DOM 元素位于侧边导航栏的子菜单之外时,它工作正常。当我将该元素放入子菜单时,Blazor 抱怨它 cannot set property 'onclick' of null

这是我的导航栏 HTML 和 JS Interop 代码

@inject IJSRuntime JS;

<div class="top-row pl-4 navbar navbar-dark">
    <a class="navbar-brand" href="">Test</a>
    <button class="navbar-toggler" @onclick="ToggleNavMenu">
        <span class="navbar-toggler-icon"></span>
    </button>
</div>

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <ul class="nav flex-column">
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="/" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </li>

        <li class="nav-item px-3">
            <NavLink class="nav-link" @onclick="()=>expandSubNav = !expandSubNav">
                <span class="oi oi-fork" aria-hidden="true"></span> AccountPage
            </NavLink>
            @if (expandSubNav)
            {
        <ul  class="nav flex-column" id="submenu">
            <li class="nav-item px-3">
                <a class="expand-menu" href="page">
                    <span>element1</span>
                </a>
            </li>
            <li class="nav-item px-3">
                <a class="expand-menu" href="page">
                    <span>element2</span>
                </a>
            </li>
            <li class="nav-item px-3">
                <a class="expand-menu" href="page">
                    <span>element3</span>
                </a>
            </li>
            <li class="nav-item px-3">
                <a class="expand-menu">
                   
                    <div   id="addBtn" ><span class="oi oi-plus" aria-hidden="true"></span> Add Element</div>
                    </a>
            </li>
      


        </ul>
            }
        </li>
       
        

    </ul>
</div>

<div id="myModal" class="modal">

    <!-- Modal content -->
    <div class="modal-content">
        <h1 class="modal-title">
            <b>Add Element Here</b>
        </h1>

        <input id="addelementtext" type="text" />
        <button id="add">Add</button>
        <button type="button" class="btn btn-defaultcloseissue" id="closebtn" data-dismiss="modal" onclick="">Close</button>



    </div>
</div>





    </div>
</div>
@code { private bool collapseNavMenu = true;
    private bool expandSubNav;

    private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;

    private void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {


        if (firstRender)
        {
            
                await JS.InvokeVoidAsync("createModal");
            
        }
    }

}

我正在尝试对这个 id 元素使用 onclick

<li class="nav-item px-3">
                <a class="expand-menu">
                   
                    <div   id="addBtn" ><span class="oi oi-plus" aria-hidden="true"></span> Add Element</div>
                    </a>
            </li>

它在它创建的子菜单中。当我把它放在子菜单外到主导航菜单时,JS 函数没有报错而且工作正常。

我也试过这样做

 protected override async Task OnAfterRenderAsync(bool firstRender)
    {


        if (firstRender)
        {
            if (expandSubNav)
            {
                await JS.InvokeVoidAsync("createModal");

            }
        }
    }

这会停止错误,但单击该元素不会执行任何操作。我该如何解决这个问题?我正在尝试研究 Blazor LifeCycle,因为我觉得这是一个渲染问题,但我很难理解我能做什么。

这里也是我要调用的JS函数

window.createModal = function createModal() {
    var modal = document.getElementById("myModal");

    // Get the button that opens the modal
    var btn = document.getElementById("addBtn");
    var closebtn = document.getElementById("closebtn");


    // When the user clicks the button, open the modal
    btn.onclick = function () {
        modal.style.display = "block";
    }



    // When the user clicks anywhere outside of the modal, close it
    window.onclick = function (event) {
        if (event.target == modal) {
            modal.style.display = "none";
        }
    }
    closebtn.onclick = function (event) {

        modal.style.display = "none";
    }
}

您的第一个错误 cannot set property 'onclick' of null 发生是因为在首次呈现导航栏时子导航部分未展开,因此 addBtn 元素尚未在 DOM 中找到当你打电话给 var btn = document.getElementById("addBtn");

第二个问题是因为您的 if() 语句仅在第一次渲染时运行一次,而 expandSubnav 是错误的。所以你的 await JS.InvokeVoidAsync("createModal"); 行永远不会被执行。

如果您注意到 @code 块中有一种切换 collapseNavMenu:

的方法
private void ToggleNavMenu()
{
    collapseNavMenu = !collapseNavMenu;
}

如果您做了类似的事情,但是 expandSubnav,您可以利用它作为挂钩 createModal 代码的机会。你只想做一次,所以你可能也想跟踪它。类似于:

private bool modalCreated = false;
private void ToggleSubNav()
{
    expandSubnav = !expandSubnav;
    if(!modalCreated)
    {
        await JS.InvokeVoidAsync("createModal");
        modalCreated = true;
    }
}

然后将其连接到您的 NavLink:

<NavLink class="nav-link" @onclick="ToggleSubNav">
    <span class="oi oi-fork" aria-hidden="true"></span> AccountPage
</NavLink>