微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在同一个 Razor 页面中使用同一个视图组件和 Javascript 文件的多个实例?

如何解决如何在同一个 Razor 页面中使用同一个视图组件和 Javascript 文件的多个实例?

我有一个 razor 页面,我将两个或多个相同类型/源的视图组件导入到一个 razor 页面中。视图组件本质上是相同的,但每个实例将从数据库加载不同的值,具体取决于表单实例上的放置选择以及通过 SignalR 来自不同源的流事件

因为每个视图组件本质上都指向同一个 javascript 文件,所以我发现只有这个视图组件的第一个加载的实例是可操作的。

我不确定如何配置 razor 以便它将每个加载的视图组件视为一个单独的实例,因此我可以将视图组件中的每个 razor 表单视为一个单独的实例。这个问题也可能会影响我有一个文本区域的事实,该文本区域将由 SignalR 动态更新

<div class="container-fluid h-100 p-0 m-0">
<div class="row justify-content-center h-100 pl-0">
    @Html.AntiForgeryToken()
    <div class="col-12 col-sm-12 col-md-6">
        @await Component.InvokeAsync("EventsMonitor")
        <script defer src="~/js/eventsmonitor-custom-scripts/eventsMonitor.js"></script>
    </div>
    <div class="col-12 col-sm-12 col-md-6 pl-sm-3 pl-md-2 pt-3 pt-sm-3 pt-md-0">
        @await Component.InvokeAsync("EventsMonitor")
        <script defer src="~/js/eventsmonitor-custom-scripts/eventsMonitor.js"></script>
    </div>
</div>

enter image description here

解决方法

好的,我就是这样解决的:

首先,我们不想在每个 razor 页面上多次加载引用 JavaScript 文件,我相信浏览器在这一点上有一些智能,但为了整理我原始问题中的代码,让我们移动脚本到剃刀代码块下面:

Razor 页面(将显示同一视图组件的多个实例)

@model MyProject.Pages.EventsMonitor.ViewEventsModel
@{
}

<div class="container-fluid h-100 p-0 m-0">
    <div class="row justify-content-center h-100 pl-0">
        @Html.AntiForgeryToken()
        <div class="col-12 col-sm-12 col-md-6">
            @await Component.InvokeAsync("EventsMonitor")
        </div>
        <div class="col-12 col-sm-12 col-md-6 pl-sm-3 pl-md-2 pt-3 pt-sm-3 pt-md-0">
            @await Component.InvokeAsync("EventsMonitor")
        </div>
    </div>
</div>

<!-- By using 'defer' you are telling the parser not to execute
   it until the document had loaded thus avoiding the problem
   of the having to put it in the layout for proper execution.
   Defer is supported by chrome,safari,and ie(10+),ff(3.6+),o(15+) -->
<script defer src="~/js/eventsmonitor-custom-scripts/eventsMonitor.js"></script>

在上面,你会看到我们引用了

@model MyProject.Pages.EventsMonitor.ViewEventsModel

这是我创建的一个新类,用于引用一个整数 (Counter),每次加载视图组件的新实例时,我们都会递增该整数。

接下来我们创建一个小的公共类:

namespace MyProject.Models.EventsMonitor
{
    public class EventsMonitorViewModel
    {
        public int Counter { get; set; }
    }
}

现在在 ViewComponent.cs 文件中,我们修改返回视图的方法:

namespace MyProject.ViewComponents
{
    public class EventsMonitor : ViewComponent
    {
        [BindProperty] // Bind to the small class we created in previous step.
        public EventsMonitorViewModel EventsMonitorViewModel { get; set; }

        private static int _value = 0;

        public IViewComponentResult Invoke()
        {
            var EventsMonitorViewModel = new EventsMonitorViewModel
            {
                // See MS Link in notes for an increment function.
                Counter = Interlocked.Increment(ref _value)
            };

            return View(EventsMonitorViewModel);
        }
    }
}

MS 递增指南在这里:https://docs.microsoft.com/en-us/dotnet/api/system.threading.interlocked.increment?view=net-5.0

所以本质上,每次我们加载同一个视图组件的新实例时,都会返回 Razor 视图以及我们绑定到 razor 页面的视图模型类。

在我的视图组件 Razor 文件(Default.cshtml 文件)中,我们修改了我们将使用 JavaScript 与之交互的每个 razor/html 组件的 Id。我不打算包含整个文件,但下面显示了剃刀表单的示例部分(您可以在我在原始问题中显示的图像中看到这些下拉选择框):

@model WebApp_PLUGIN.Models.EventsMonitor.EventsMonitorViewModel

<div class="form-group" style="margin-top: 1.5em">
    <div class="row">
        <div class="col-sm">
            <label class="control-label">Plugin Type</label>
            <select class="form-control" id="@("pluginTypeSelect"+Model.Counter)" onchange="pluginTypeSelect(this.id)">
                <option value="">Select</option>
                    <option value="RS232Port">RS232 Port</option>
                    <option value="SmtpServer">SMTP Server</option>
                    <option value="TcpClient">TCP Client</option>
                    <option value="TcpServer">TCP Server</option>
            </select>
        </div>
        <div class="col-sm mt-sm-0 mt-3">
            <label class="control-label">Source</label>
                <select class="form-control" id="@("pluginSourceSelect"+Model.Counter)">
                    <option value="">Select</option>
                </select>
            </div>
        </div>
        <div class="text-danger" id="@("eventsMonitorMessageBarTop"+Model.Counter)"  style="white-space: pre-line"></div>
    </div>
</div>

在上面的 Razor 代码块中,对于每个元素 Id,我们将计数器变量添加到 Id 字符串的末尾,以便在加载视图组件的每个实例时,每个元素都会有一个唯一的 Id,它会向上递增 +1 .

因此,以上所有的结果是,当在 razor 中为 UI 组件的逻辑使用 JavaScript 函数时,每个视图组件和关联的表单元素都将具有唯一的 Id。 下面是用于测试的示例 JavaScript 代码:

function pluginTypeSelect(clicked_id) {

    // Each dropown select from each instance of the View Component will have a unique Id
    alert(clicked_id) 
}

在我的测试中,参考我原始问题中的屏幕截图,LHS View Component 上的下拉选择生成和 Id "pluginTypeSelect1" 和 RHS View Component 生成和 Id "pluginTypeSelect2"

我还没有解决的唯一部分是每次加载 Razor 页面时“Counter”变量都会增加 +1,这对我来说不是一个问题,但可能是一个运行时间很长的应用程序最好在某个时候再次将整数重置为零,这样你就不会得到一个长整数。我会为此想出一个解决方案,然后更新我的答案。

希望这能帮助遇到类似难题的其他人......

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?