如何封装ASP.NET MVC 3 + Razor视图的可重用“控件”

时间:2010-11-26 23:02:50

标签: javascript asp.net-mvc razor

我正在寻找有关如何创建可重用“控件”以便在多个MVC 3视图上使用的最佳实践。我可以创建一个Html帮助扩展方法(以编程方式或在razor中使用声明性帮助器)或者我可以创建一个局部视图。

在我的情况下,技巧是我需要做的不仅仅是在视图调用helper / partial的地方转储一些HTML。除了在该位置放置一些HTML标记之外,我还需要添加一些javascript代码以使其工作。通常,我会将此代码放在页面的其他位置(例如底部)。这当然是严格要求的。另外,请注意,javascript不是特定于控件实例的。换句话说,可以编写javascript,在页面上查找控件HTMl标记的所有实例,并使用适当的事件“激活”它等。

我想到了几种可能性。

  1. 帮助/部分转储HTML和<script>标记,直到它被调用的地方。这似乎是一个坏主意,因为这意味着每页只能使用一次控件。
  2. 有两个帮手。一个用于输出HTML标记,另一个用于输出javascript。第二个只会被调用一次,并将从页面底部调用,以便脚本最终到达正确的位置。如果我发明了第二个这样的控件,我会有4个帮助器(2个用于HTML,2个用于Javascript)。
  3. 创建某种控件可以注册javascript的ScriptManager。 scriptmanager会有一些帮助,它会被添加到页面底部,并会为已经注册了一些脚本片段的所有控件转储javascript。对scriptmanager助手的调用可能在_layout.cshtml中,因此它会自动发生在需要它的任何页面上。当页面不需要它时,它什么都不做。这似乎不是MVC-ish,我想。
  4. 只需要一个帮助器,它会吐出HTML,然后将javascript添加到每个页面上包含的site.js中。如果javascript在页面上找不到任何相关的标记,那么javascript就足够聪明,不会做任何事情(标记会有一个包含特定类的包装元素)。但是,在所有页面上搜索标记会有开销,包括没有任何这些控件的页面。
  5. 与#4相同,但将javascript放在自己的.js文件中,并仅将其包含在使用该控件的页面上。这对于不使用该控件的页面更有效,但它是一个额外的.js文件和相关的HTTP请求。
  6. 我倾向于#4,但这是一个解决的问题吗?有没有更好的第六种选择?

2 个答案:

答案 0 :(得分:2)

我的公司正在使用MVCContrib便携式区域将代码打包成DLL,以便重用“组件”

可以通过扩展方法调用这些组件中的每一个。例如:

Html.Components().ShowPoll();

在每个组件中,有一种方法可以注册多个嵌入资源的css / js文件。我们的主站点将提取资源文件并在服务之前缩小+组合它们。

该组件还将注册将在JQuery的Document.OnReady事件期间调用的任何页面事件。这允许每个组件都是迷你站点,具有自己的路由,模型和视图的独立功能。

在整个网站上,提供了所有组件的相同拉链JS。一个是因为文件将被缓存,两个 - 消除了确定页面上的组件及其所需资源的复杂性。

如果您想了解有关此设置的更多信息,请与我们联系。

答案 1 :(得分:0)

我使用一个名为jsCode的部分的布局页面来管理这个问题。

@RenderSection("jsCode",false)

然后当我需要它时,我在内容页面中创建:

@section jsCode
{
<script type="text/JavaScript" src="myJsCode.js"></script>
}

您还可以创建一个帮助程序,它会为特定页面扫描您需要的脚本并以这种方式封装它,如下所示:

 @helper MyJSFunction(string FunctionName){

        switch(FunctionName)
        {
            case "firstFN":
        <text>
    <script type="text/JavaScript">
        function SaySomethingSilly()
        {
            var sillySaying="We are the knights who say 'ni'!";
            alert(sillySaying);
        }
        </script>
        </text>

        break;
        case "secondFN":
        <text>
        <script type="text/JavaScript">
                function SaySomethingElse()
        {   var sillySaying="We are looking for a shrubbery...";
            alert(sillySaying);
        }   
        </script>
        </text>
    break;
    }
    }

然后我的内容页面(假设我想要两个函数)看起来像这样:

@{
Page.Title="Using helpers to create scripts";}
@section jsCode
{
@JSHelpers.MyJSFunction("firstFN")
@JSHelpers.MyJSFunction("secondFN")
}
<p>It works!</p>

产生了输出:

<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Using helpers to create scripts</title>


<script type="text/JavaScript">
    function SaySomethingSilly()
    {
        var sillySaying="We are the knights who say 'ni'!";
        alert(sillySaying);
    }
    </script>


    <script type="text/JavaScript">
            function SaySomethingElse()
    {   var sillySaying="We are looking for a shrubbery...";
        alert(sillySaying);
    }   
    </script>



    </head>
    <body>

<p>It works!</p>
    </body>
</html>

现在,如果你想要超高效,(虽然可以想到其他的话)你可以传递一个JSON数组或字典,甚至是一个字符串数组,其中包含你想要使用的脚本的名称,或者要导入的JavaScript,或者其他什么,只需使用一次调用帮助程序。我认为无论你如何加载辅助函数的返回值,单独调用都更容易维护,因为你可以清楚地看到你在给定页面上使用哪些脚本,并且消除或添加一个是简单的-line更改而不是更改数组的一个元素。

与往常一样,您的里程可能会有所不同,但我在WebMatrix Beta 2中根据此代码运行了示例,没有任何问题。

Lisa Z. Morgan http://www.lairhaven.com