[ASP.NET MVC 小牛之路]17 - 捆绑(Bundle)

2023-12-22 15:20
文章标签 mvc 17 asp net bundle 捆绑 小牛

本文主要是介绍[ASP.NET MVC 小牛之路]17 - 捆绑(Bundle),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文介绍 MVC 4 提供的一个新特性:捆绑(Bundle),一个在  View 和 Layout 中用于组织优化浏览器请求的 CSS 和 JavaScript 文件的技术。

本文目录

了解VS默认加入的脚本库

当我们创建一个基本模板的 MVC 工程时,VS在Scripts文件夹中默认加入了一些 JavaScript 脚本库。下面是这些脚本库的简单介绍:

  • jquery-1.8.2.js,这个就不用解释了。
  • jquery-ui-1.8.24.js,在jQuery 基础上的一套界面工具,包括了网页上常见的很多插件和动画特效。
  • jquery.validate.js,用于验证用户在表单内input元素输入的数据。
  • knockout-2.2.0.js,是一个轻量级的UI类库,通过应用MVVM模式使JavaScript前端UI简单化,更多:http://knockoutjs.com/documentation/introduction.html。
  • modernizr-2.6.2.js,一个开源的JS库,它使得那些基于访客浏览器的不同(指对新标准支持性的差异)而开发不同级别体验的设计师的工作变得更为简单。它使得设计师可以在支持HTML5和CSS3的浏览器中充分利用HTML5和CSS3的特性进行开发,同时又不会牺牲其他不支持这些新技术的浏览器的控制。更多:http://www.mhtml5.com/2011/03/676.html 。
  • jquery.unobtrusive-ajax.js,MVC 框架中使用 Unobtrusive Ajax 的库,更多:[ASP.NET MVC 小牛之路]14 - Unobtrusive Ajax 。
  • jquery.validate.unobtrusive.js,基于 jquery.unobtrusive-ajax.js,更多:[ASP.NET MVC 小牛之路]15 - Model Binding 。

另外还有一个 _references.js 文件,它的作用是通过下面这种方式放入该文件中的JS文件可以被VS智能感知:

/// <reference path="jquery-1.8.2.js" />
/// <reference path="jquery-ui-1.8.24.js" />

相关小技巧:在VS中让一个JS文件智能提示另一个JS文件中的成员 。

在实际的项目中,我们可能远远不止引入上面这些脚本文件,MVC 4提供的“捆绑”新功能可以很方便地对引入的脚本文件进行管理。

准备工作

选择基本模板创建一个MVC工程。和前一篇的示例差不多,创建一个名为 Appointment 的 Model,代码如下:

public class Appointment {[Required]public string ClientName { get; set; }[DataType(DataType.Date)]public DateTime Date { get; set; }public bool TermsAccepted { get; set; }
}
Appointment

添加一个 HomeController,代码如下:

public class HomeController : Controller {public ViewResult MakeBooking() {return View();}[HttpPost]public JsonResult MakeBooking(Appointment appt) {return Json(appt, JsonRequestBehavior.AllowGet);}
}
HomeController

给MakeBooking action添加一个 MakeBooking.cshtml 视图,代码如下:

@model MvcApplication1.Models.Appointment
@{AjaxOptions ajaxOpts = new AjaxOptions {OnSuccess = "processResponse"};
}
<h4>Book an Appointment</h4><script src="~/Scripts/Home/MakeBooking.js"></script><div id="formDiv" class="visible">@using (Ajax.BeginForm(ajaxOpts)) {@Html.ValidationSummary(true)<p>@Html.ValidationMessageFor(m => m.ClientName)</p><p>Your name: @Html.EditorFor(m => m.ClientName)</p><p>@Html.ValidationMessageFor(m => m.Date)</p><p>Appointment Date: @Html.EditorFor(m => m.Date)</p><p>@Html.ValidationMessageFor(m => m.TermsAccepted)</p><p>@Html.EditorFor(m => m.TermsAccepted) I accept the terms & conditions</p><input type="submit" value="Make Booking" />}
</div>
<div id="successDiv" class="hidden"><h4>Your appointment is confirmed</h4><p>Your name is: <b id="successClientName"></b></p><p>The date of your appointment is: <b id="successDate"></b></p><button id="backButton">Back</button>
</div>

把该视图需要的 JavaScript 代码放在一个单独的文件 MakeBooking.js 中,并将该JS文件放在 /Scripts/Home 文件夹下,该JS文件代码如下:

function processResponse(appt) { $('#successClientName').text(appt.ClientName);$('#successDate').text(processDate(appt.Date));switchViews();
}
function processDate(dateString) {var date = new Date(parseInt(dateString.substr(6, dateString.length - 8)));return date.toLocaleDateString();
}
function switchViews() {var hidden = $('.hidden');var visible = $('.visible');hidden.removeClass("hidden").addClass("visible");visible.removeClass("visible").addClass("hidden");
}
$(document).ready(function () {$('#backButton').click(function (e) {switchViews();});
});
MakeBooking.js

注意,这里需要对后台通过Json方法返回的日期进行处理,Json 方法返回的日期格式是:/Date(1385308800000)/,所以把它呈现给客户端时用 processDate JS方法处理了一下。

在 Content 文件夹下添加一个样式文件 CustomStyles.css,代码如下:

div.hidden { display: none;} 
div.visible { display: block;}

最后清理一下 _Layout.cshtml 文件,如下:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8" /><meta name="viewport" content="width=device-width" /><title>@ViewBag.Title</title>
</head>
<body>@RenderBody()
</body>
</html>
_Layout.cshtml

本文将关心的是 JS 和 CSS 文件的引用,大家不用关心代码本身,此时只需Copy好代码,一会使用捆绑让它运行起来。 

使用捆绑管理脚本和样式文件

以前我们引入脚本和样式文件的时候,都是一个个的引用,看起来一大坨,不小心还会弄错先后次序,管理很是不便。而且很多脚本库有普通和 min 两个版本,开发的时候我们引入普通版本以方便调试,发布的时候又换成min版本以减少网络带宽,很是麻烦。为此,MVC 4 增加了一个新功能:“捆绑”,它的作用是把一类脚本或样式文件捆绑在一起,在需要用的时候调用一句代码就行,极大地方便了脚本和样式文件的管理;而且可以把脚本的普通和 min 两个版本都捆绑起来,MVC也会根据是否为Debug模式智能地选择脚本文件的版本。下面我们来看看这个捆绑功能的使用。

用捆绑方便之一是可以在 /App_Start/BundleConfig.cs 中通过注册来统一管理脚本和样式文件。我们可以打开 BundleConfig.cs 文件看看VS 已经默认对脚本和样式文件的捆绑情况。为了演示如何使用捆绑,我们把VS默认的捆绑代码删除,再增加我们需要的捆绑,如下所示:

public class BundleConfig {public static void RegisterBundles(BundleCollection bundles) {bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/*.css"));bundles.Add(new ScriptBundle("~/bundles/clientfeaturesscripts").Include("~/Scripts/jquery-{version}.js","~/Scripts/jquery.validate.js","~/Scripts/jquery.validate.unobtrusive.js","~/Scripts/jquery.unobtrusive-ajax.js"));}
}

捆绑是通过 RegisterBundles 参数对象的 Add 方法添加。Add 方法的参数需要一个ScriptBundle 类 或 StyleBundle 类的实例对象, 脚本文件用的是 ScriptBundle 类,样式文件用的是 StyleBundle 类,它们的构造参数代表着捆绑在一起的文件的引用。 Include 方法用于包含具体要捆绑的文件。其中的 {version} 是文件版本的占位符,MVC会在相应的目录下定位到最新的一个版本文件。

使用捆绑方便之二是再也不用引入一大坨的文件了,如下面的 _Layout.cshtml:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8" /><meta name="viewport" content="width=device-width" /><title>@ViewBag.Title</title>@Styles.Render("~/Content/css")
</head>
<body>@Scripts.Render("~/bundles/clientfeaturesscripts")@RenderBody()
</body>
</html>

这里通过 @Scripts.Render 和 @Styles.Render 两个Helper方法添加捆绑。需要注意的是,MakeBooking.cshtml 文件引入的 MakeBooking.js 是基于 jQuery的,所以 _Layout.cshtml的 @Scripts.Render("~/bundles/clientfeaturesscripts") 必须放在 @RenderBody() 之前。

使用脚本 Section

上面我们提到在 _Layout.cshtml 中,@Scripts.Render("~/bundles/clientfeaturesscripts") 必须放在 @RenderBody() 之前,因为View引入的JS是基本jQuery的。有时候由于某种需求或个人的喜好要把 @RenderBody() 放在 @Scripts.Render("~/bundles/clientfeaturesscripts") 之前,如果这样的话,MakeBooking.js 文件就在jQuery库之前引用了,显然JS会报错。

对于这种情况,我们可以用 [ASP.NET MVC 小牛之路]12 - Section、Partial View 和 Child Action 文章介绍的Section来解决这种JS引用次序的问题。如下,我们可以把 MakeBooking.cshtml 中引入JS的部分用section包起来:

...
<h4>Book an Appointment</h4> 
@section scripts { <script src="~/Scripts/Home/MakeBooking.js" type="text/javascript"></script> 
} 
...

然后我们就可以在 _Layout.cshtml 所有Render方法后面使用  @RenderSection("scripts", required: false) 方法引入MakeBooking.js 文件,这样就不用关心在 _Layout.cshtml 中的 @RenderBody() 和 @Scripts.Render("~/bundles/clientfeaturesscripts") 的先后次序了。如下所示:

<body> @RenderBody() @Scripts.Render("~/bundles/clientfeaturesscripts") @RenderSection("scripts", required: false) 
</body> 

这样保证了 MakeBooking.js 一定在jQuery库文件之后引用。

使用捆绑带来的改变

捆绑除了可以方便地管理脚本和样式文件,还可以给网络减少带宽。

以下是在Debug模式下使用捆绑MVC生成引用部分的代码:

<link href="/Content/CustomStyles.css" rel="stylesheet"/>
<link href="/Content/Site.css" rel="stylesheet"/>
...
<script src="/Scripts/jquery-1.8.2.js"></script>
<script src="/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>
...
<script src="/Scripts/Home/MakeBooking.js"></script>

总共 7 个文件,在Debug模式下使用捆绑和不使用捆绑没什么区别。

下面我们来比较一下在发布模式下不使用捆绑和使用捆绑两者使用带宽的情况。

在 Web.config 中把调式模式关闭,如下:

...
<system.web><httpRuntime targetFramework="4.5" /><compilation debug="false" targetFramework="4.5" />
...

我们先来看看不使用捆绑使用带宽的情况,为此,我们 MakeBooking.cshtml 中的section部分 和 _Layout.cshtml 中的引用捆绑的部分注释掉。并在 _Layout.cshtml 中引入上面 7 个文件,如下:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8" /><meta name="viewport" content="width=device-width" /><title>@ViewBag.Title</title>@*@Styles.Render("~/Content/css")*@<link href="~/Content/CustomStyles.css" rel="stylesheet"/>    <link href="~/Content/Site.css" rel="stylesheet" /><script src="~/Scripts/jquery-1.8.2.js"></script><script src="~/Scripts/jquery.unobtrusive-ajax.js"></script><script src="~/Scripts/jquery.validate.js"></script><script src="~/Scripts/jquery.validate.unobtrusive.js"></script><script src="~/Scripts/Home/MakeBooking.js"></script>
</head>
<body>@RenderBody()@*@Scripts.Render("~/bundles/clientfeaturesscripts")@RenderSection("scripts", required: false)*@
</body>
</html>

运行程序,用IE F12 工具查看请求服务器资源的情况(注意要先清理缓存),结果如下:

我们看到在不使用捆绑的情况下,客户端接收的数据总大小为330.65 KB。

我们再来看看使用捆绑带宽的使用情况。我们把之前在 MakeBooking.cshtml 和 _Layout.cshtml 中的注释去掉,并把 _Layout.cshtml 引入 7 个文件的代码删除。

运行程序(注意清涂缓存),结果如下:

我们看到,使用捆绑客户端接收的数据总大小为 124.01 KB,和不使用捆绑相比少200多KB,即一半多,这是非常可观的。

我们也注意到,使用捆绑请求的链接也少了。这是因为在发布模式下,响应客户端请求时,MVC整合并最小化了JavaScript文件和样式文件,并使得一个捆绑中的内容在一个请求中加载。如果我们查看Html代码,可以看到 Styles.Render 和 Scripts.Render 两个方法生成了这样的HTML引用代码:

<link href="/Content/css?v=6jdfBoUlZKSHjUZCe_rkkh4S8jotNCGFD09DYm7kBWE1" rel="stylesheet"/>
...
<script src="/bundles/clientfeaturesscripts?v=KyclumLmAXQGM1-wDTwVUS31lpYigmXXR8HfERBGk_I1"></script>
..
<script src="/Scripts/Home/MakeBooking.js"></script>

一个Styles.Render 或 Scripts.Render 方法生成了一个带有v参数的URL,这个URL将使MVC把一整个捆绑的数据进行最小化处理并一次发送到客户端。

 


参考:《Pro ASP.NET MVC 4 4th Edition》

这篇关于[ASP.NET MVC 小牛之路]17 - 捆绑(Bundle)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/524460

相关文章

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

2、PF-Net点云补全

2、PF-Net 点云补全 PF-Net论文链接:PF-Net PF-Net (Point Fractal Network for 3D Point Cloud Completion)是一种专门为三维点云补全设计的深度学习模型。点云补全实际上和图片补全是一个逻辑,都是采用GAN模型的思想来进行补全,在图片补全中,将部分像素点删除并且标记,然后卷积特征提取预测、判别器判别,来训练模型,生成的像

Spring MVC 图片上传

引入需要的包 <dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.1</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

MVC(Model-View-Controller)和MVVM(Model-View-ViewModel)

1、MVC MVC(Model-View-Controller) 是一种常用的架构模式,用于分离应用程序的逻辑、数据和展示。它通过三个核心组件(模型、视图和控制器)将应用程序的业务逻辑与用户界面隔离,促进代码的可维护性、可扩展性和模块化。在 MVC 模式中,各组件可以与多种设计模式结合使用,以增强灵活性和可维护性。以下是 MVC 各组件与常见设计模式的关系和作用: 1. Model(模型)

17 通过ref代替DOM用来获取元素和组件的引用

重点 ref :官网给出的解释是: ref: 用于注册对元素或子组件的引用。引用将在父组件的$refs 对象下注册。如果在普通DOM元素上使用,则引用将是该元素;如果在子组件上使用,则引用将是组件实例: <!-- vm.$refs.p will be the DOM node --><p ref="p">hello</p><!-- vm.$refs.child will be the c

react笔记 8-17 属性绑定 class绑定 引入图片 循环遍历

1、绑定属性 constructor(){super()this.state={name:"张三",title:'我是一个title'}}render() {return (<div><div>aaaaaaa{this.state.name}<div title={this.state.title}>我是一个title</div></div></div>)} 绑定属性直接使用花括号{}   注

.NET 自定义过滤器 - ActionFilterAttribute

这个代码片段定义了一个自定义的 ASP.NET Core 过滤器(GuardModelStateAttribute),用于在控制器动作执行之前验证模型状态(ModelState)。如果模型状态无效,则构造一个 ProblemDetails 对象来描述错误,并返回一个 BadRequest 响应。 代码片段: /// <summary>/// 验证 ModelState 是否有效/// </

【全网最全】2024年数学建模国赛A题30页完整建模文档+17页成品论文+保奖matla代码+可视化图表等(后续会更新)

您的点赞收藏是我继续更新的最大动力! 一定要点击如下的卡片,那是获取资料的入口! 【全网最全】2024年数学建模国赛A题30页完整建模文档+17页成品论文+保奖matla代码+可视化图表等(后续会更新)「首先来看看目前已有的资料,还会不断更新哦~一次购买,后续不会再被收费哦,保证是全网最全资源,随着后续内容更新,价格会上涨,越早购买,价格越低,让大家再也不需要到处买断片资料啦~💰💸👋」�