【问题标题】:How to use @section scripts in a partial view MVC.Core如何在局部视图 MVC.Core 中使用 @section 脚本
【发布时间】:2019-11-17 00:02:52
【问题描述】:

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

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

如果布局包含:

@RenderSection("Scripts", required: false)

您的脚本将被渲染。这在每个示例中都派上用场,以保证脚本将在所有 javascript 包含(如 jQuery)之后呈现。

但是如何在局部视图中渲染脚本呢?

【问题讨论】:

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


【解决方案1】:

这是一个解决方案:

在布局页面中:

@Html.PageScripts()

在局部:

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

以及 MVC.core 的 Helper 类

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 中导入您的类助手,以便您可以在所有视图中使用它。

【讨论】:

  • 类似于我的Answer,因为我的Answer Here,我不再使用。
  • 只是想说谢谢你,我用这个 sn-p 做了一个非常优雅的解决方案用于开发目的:)
【解决方案2】:

通常这是一个坏主意,因为您没有捆绑/缩小脚本。

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

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

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

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

不可重复使用,因为无论型号如何,同一页面的所有组件都将具有相同的宽度。

相反,您可以创建单个脚本文件并使用 data-* attributes 来存储配置信息并让单个脚本解决它(就像许多库所做的那样,例如引导程序):

<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

【讨论】:

  • 这是一些常识,当人们想要以简单(当然是短期)的方式进行操作时,它很快就会被抛弃。实现这一点可能需要一些努力(例如,如果您想在脚本中使用 @Url.Action()),但这是值得的。
猜你喜欢
  • 1970-01-01
  • 2012-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-29
  • 2012-01-29
相关资源
最近更新 更多