天天看點

ASP.NET MVC 4 (十一) Bundles和顯示模式

Bundles用于打包CSS和javascript腳本檔案,優化對它們的組織管理。顯示模式則允許我們為不同的裝置顯示不同的視圖。

預設腳本庫

在VS建立一個MVC工程,VS會為我們在scripts目錄下添加很多腳本庫,下面來簡單了解下這些腳本庫的作用:

腳本檔案 說明
jquery-1.7.1.js jquery的基本類庫
jquery-ui-1.8.20.js jquery的UI類庫,友善我們建立豐富的使用者控件,基于jquery基本類庫
jquery.mobile-1.1.0.js 用于移動裝置UI控件的類庫,在建立移動模闆的工程時添加
jquery-validate.js  用于用戶端驗證的類庫
knockout-2.1.0.js  用戶端的模型-視圖-視圖模式類庫,在用戶端将顯示資料和沒模型分開,可以認為是浏覽器上的MVC
modernizr-2.5.3.js  用于檢測浏覽器對HTML5和CSS3的支援
jquery-1.7.1.intellisense.js  用于Visual studio在編寫jQuery代碼時提供函數名稱的提示
jquery.unobtrusive-ajax.js  用于MVC架構的unobtrusive Ajax功能
jquery.validate-vsdoc.js  用于Visual studio在編寫jQuery驗證函數時提示函數名稱
jquery.validate.unobtrusive.js 用于MVC的用戶端驗證,依賴jquery-validate.js 

一些腳本檔案有正常和最小化兩個版本,最小化版本删除注釋剪短變量名以縮小檔案尺寸,在功能上和正常版本一緻。正常版本的jquery-1.7.1.js檔案大小252K,而縮小版的jquery-1.7.1.min.js隻有92K,如果網站每天數以百萬計的通路量,帶來的流量節省還是很巨大的。縮小版的腳本很難閱讀,是以開發時我們使用正常版本的腳本庫友善調試,釋出時再切換為縮小版本。

打包腳本和風格

Bundles定義在/App_Start/BundleConfig.cs檔案,VS為我們建立的預設實作:

public class BundleConfig {
        // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725
        public static void RegisterBundles(BundleCollection bundles) {
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include("~/Scripts/jquery-{version}.js"));
            bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include("~/Scripts/jquery-ui-{version}.js"));
            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include("~/Scripts/jquery.unobtrusive*","~/Scripts/jquery.validate*"));

            // Use the development version of Modernizr to develop with and learn from. Then, when you're
            // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include("~/Scripts/modernizr-*"));
            bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));
            bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
                        "~/Content/themes/base/jquery.ui.core.css",
                        "~/Content/themes/base/jquery.ui.resizable.css",
                        "~/Content/themes/base/jquery.ui.selectable.css",
                        "~/Content/themes/base/jquery.ui.accordion.css",
                        "~/Content/themes/base/jquery.ui.autocomplete.css",
                        "~/Content/themes/base/jquery.ui.button.css",
                        "~/Content/themes/base/jquery.ui.dialog.css",
                        "~/Content/themes/base/jquery.ui.slider.css",
                        "~/Content/themes/base/jquery.ui.tabs.css",
                        "~/Content/themes/base/jquery.ui.datepicker.css",
                        "~/Content/themes/base/jquery.ui.progressbar.css",
                        "~/Content/themes/base/jquery.ui.theme.css"));
        }
    }      

ScriptBundle建立腳本包,StyleBundle建立CSS風格包,兩者都使用Include包含一組檔案。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"));

        }
    }      

注意這裡的“~/Scripts/jquery-{version}.js”,{version}比對對應檔案的任何版本并通過工程配置檔案選擇正常版本還是縮小版,具體是web.config中的debug設定,如果為true選擇正常版本,false則是縮小版。需要注意的是我們不能把相同檔案的不同版本号放在一起,比如“jquery-1.7.2.js”和“jquery-1.7.1.js”,兩個版本号都會被發送給用戶端反而造成混淆。

在布局檔案中使用Scripts.Render()輸出腳本包,Styles.Render()輸出風格包:

<!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>
    @RenderBody()

    @Scripts.Render("~/bundles/clientfeaturesscripts")

    @RenderSection("scripts", required: false)
</body>
</html>      

生成的HTML檔案會通過<link href="XXX" rel="stylesheet"/>包含所有包裡的CSS檔案,所有的腳本檔案則通過<script src="XXX"></script>引用。

上面的例子中還使用“@RenderSection("scripts", required: false)”輸出一個節,requried=false表示不是必須的,隻有在視圖檔案中定義了這個節才會渲染,我們可以利用它來包含視圖需要的額外腳本檔案,比如我們在MakeBooking.cshtml中定義Scripts節來包含腳本檔案:

@model ClientFeatures.Models.Appointment

@{
    ViewBag.Title = "Make A Booking";
    AjaxOptions ajaxOpts = new AjaxOptions {
        OnSuccess = "processResponse"
    };
}
<h4>Book an Appointment</h4>
@section scripts {
    <script src="~/Scripts/Home/MakeBooking.js" type="text/javascript"></script>
}
...      

使用這種可選節我們可以有選擇的視圖中包含視圖僅需的腳本檔案。

面向移動裝置

人們越來越多的使用移動裝置浏覽網站,MVC應用也要考慮如何相容這些移動裝置以提供的更好的閱讀體驗。我們可以使用安卓、蘋果手機通路開發測試網站,更友善的是從www.opera.com/developer/tools/mobile下載下傳模仿移動版本的Opera浏覽器,用它可以模仿不同裝置設定不同螢幕大小的顯示分辨率來測試。

在MVC WEB應用中我們在普通的視圖檔案外可以添加面向移動裝置的視圖,視圖檔案名裡在檔案字尾名前加入“.Mobile”表示這是移動裝置專用,比如“/Views/Home/MakeBooking.Mobile.cshtml”:

@model ClientFeatures.Models.Appointment

@{
    ViewBag.Title = "Make A Booking";
    AjaxOptions ajaxOpts = new AjaxOptions {
        OnSuccess = "processResponse"
    };
}
<h4>This is the MOBILE View</h4>
@section scripts {
    <script src="~/Scripts/Home/MakeBooking.js" type="text/javascript"></script>
}

<div id="formDiv" class="visible">
    @using (Ajax.BeginForm(ajaxOpts)) {
        @Html.ValidationSummary(true)    
        <p>@Html.ValidationMessageFor(m => m.ClientName)</p>
        <p>Name:</p><p>@Html.EditorFor(m => m.ClientName)</p>
        <p>@Html.ValidationMessageFor(m => m.Date)</p>
        <p>Date:</p><p>@Html.EditorFor(m => m.Date)</p>
        <p>@Html.ValidationMessageFor(m => m.TermsAccepted)</p>
        <p>@Html.EditorFor(m => m.TermsAccepted) 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>      

這裡适當調整控件布局以更适合在移動裝置上浏覽,其他和桌面版基本一緻。當我們從移動裝置浏覽時,MVC自動為我們應用移動版本的視圖,MVC依賴C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\Browsers目錄下的各種浏覽器的描述檔案檢查浏覽器版本,主要是比對檔案中定義的user agent特性,你會發現UC浏覽器赫然在列。

自定義顯示模式

上面的方法将所有的移動裝置歸為一類,如果我們還需要更細分具體是哪種移動裝置,我們可以通過建立自定義顯示模式來實作,這是在Application_start中注冊的:

public class MvcApplication : System.Web.HttpApplication {
        protected void Application_Start() {

            DisplayModeProvider.Instance.Modes.Insert(0,
                new DefaultDisplayMode("OperaTablet") {
                    ContextCondition = (context => context.Request.UserAgent.IndexOf("Opera Tablet", StringComparison.OrdinalIgnoreCase) >= 0)
                });

            AreaRegistration.RegisterAllAreas();
...      

這裡通過比較請求的User agent是否包含“Opera tablet”來辨別OperaTablet顯示模式,如果請求來自于這樣的裝置,MVC會查找包含OperaTablet的視圖檔案比如/Views/Home/MakeBooking.OperaTable.cshtml,這樣我們就可以單為某種裝置建立自定義的視圖。

以上為對《Apress Pro ASP.NET MVC 4》第四版相關内容的總結,不詳之處參見原版 http://www.apress.com/9781430242369。