如何在部分视图MVC.Core中使用@section脚本

时间:2019-07-07 00:17:10

标签: c# asp.net-mvc asp.net-core .net-core

在ASP.NET Core MVC中,可以为这样的页面定义脚本部分:

@section scripts {
    <script>
        alert('hello');
    </script>
}

如果布局包含:

@RenderSection("Scripts", required: false)

您的脚本将被渲染。每个示例都派上用场,以确保脚本将在所有javascript包括jQuery之类的语言之后呈现。

但是如何在局部视图中呈现脚本?

3 个答案:

答案 0 :(得分:3)

部分在局部视图中不起作用,这是设计使然。您可以use some custom帮助者实现类似的行为,但是说实话,包括必要的脚本是视图的责任,而不是部分的责任。我建议使用主视图的@scripts部分来执行此操作,而不必担心脚本的局部问题。

答案 1 :(得分:0)

这是一个解决方案:

在“布局”页面中:

@Html.PageScripts()

在部分中:

@using (Html.BeginScripts())
{
 <script>
   alert('hello');
 </script>
}

以及MVC.core的帮助器类

using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Rendering;
using System;
using System.Collections.Generic;
using System.IO;

namespace MyProjectNamespace
{
    public static class HtmlHelpers
    {
        private const string ScriptsKey = "DelayedScripts";

        public static IDisposable BeginScripts(this IHtmlHelper helper)
        {
            return new ScriptBlock(helper.ViewContext);
        }

        public static HtmlString PageScripts(this IHtmlHelper helper)
        {
            return new HtmlString(string.Join(Environment.NewLine, GetPageScriptsList(helper.ViewContext.HttpContext)));
        }

        private static List<string> GetPageScriptsList(HttpContext httpContext)
        {
            var pageScripts = (List<string>)httpContext.Items[ScriptsKey];
            if (pageScripts == null)
            {
                pageScripts = new List<string>();
                httpContext.Items[ScriptsKey] = pageScripts;
            }
            return pageScripts;
        }

        private class ScriptBlock : IDisposable
        {
            private readonly TextWriter _originalWriter;
            private readonly StringWriter _scriptsWriter;

            private readonly ViewContext _viewContext;

            public ScriptBlock(ViewContext viewContext)
            {
                _viewContext = viewContext;
                _originalWriter = _viewContext.Writer;
                _viewContext.Writer = _scriptsWriter = new StringWriter();
            }

            public void Dispose()
            {
                _viewContext.Writer = _originalWriter;
                var pageScripts = GetPageScriptsList(_viewContext.HttpContext);
                pageScripts.Add(_scriptsWriter.ToString());
            }
        }
    }
}

提示:将您的类帮助程序导入_ViewImports.cshtml,以便可以在所有视图中使用它。

答案 2 :(得分:0)

  

通常这是个坏主意,因为您不是在打包/缩小脚本。

  

@ErikPhilips那不是真的,想象我想要一个仅在该部分中运行的特定javascript代码。为什么要捆绑它并导入整个应用程序?为了缩小,我可以缩小我的打字稿文件,并将其导入到我的脚本块中的部分文件中。

  

想象一下,我想要一个只能在该部分中运行的特定javascript代码。

该脚本不会仅在该部分页面中运行,它将在整个页面中运行。它是在单个http调用中提供的客户端代码(假定正常使用,因为您未指定其他任何内容)。考虑部分:

@Model SomeModel
<div class='my-component'>
<div>
<script>
  $('.my-component').css('width', model.Width);
</script>

不可重复使用,因为所有组件在同一页面上的宽度将相同,而与型号无关。

相反,您可以创建一个脚本文件,并使用data-* attributes存储配置信息,然后由单个脚本找出该信息(就像许多MANY库一样,例如引导程序):

<div class='my-component green' data-config='{ "width": 200, "height": 200 }'>
</div>

然后在单个脚本文件中:

$(document).ready(function(){
  $('.my-component').each(function(){
    var $this = $(this);
    var config = $this.data('config');
    $this.css("width", config.width);
    $this.css("height", config.height);
  });
});
  

我为什么要捆绑它

因为它会被浏览器自动缓存。这意味着下载每个实例所需的时间更少。请考虑以下内容:

<div class='my-component'>
<div>
<script>
  // lots of scripts say 100-200 lines of it.
</script>

每次客户访问任何页面时,他们每次都必须下载完全相同的精确代码,每页可能多次下载。这样会占用不必要的客户端带宽和服务器带宽。

  

并导入整个应用程序?

您可以一次全局导入,也可以在特定布局中一次导入。因为第一次之后,它被缓存

  

为了简化,我可以创建我的打字稿文件,并将其导入到我的脚本块中的部分文件中。

然后为什么要在部分脚本中完全使用

推荐读物:Decoupling Your HTML, CSS, and JavaScript