在ASP.net MVC中利用ajax配合razor進行局部加載


在asp.net mvc中, razor引擎的作用是渲染出靜態頁面。(我這里指的靜態頁面,是指對瀏覽器而言,第一次從服務器下載以后頁面。)

而ajax的作用是瀏覽器端的頁面通過js向服務端再次發出請求從而從服務端獲取數據展示在頁面。

我們一般的編程模式是ajax只輸出json風格的數據,再由客戶端通過某種方式動態展示到頁面上,比如通過jquery的模板插件,或第三方的控件。

這種方式無疑是高效的。對服務器壓力也較小。

但是它的缺點就是我們無法利用現有的強大的razor引擎,用它豐富的Html幫助類,精確地控制數據展示的方式,維護各種鏈接。因為它是工作在服務器端的,在初始頁面第一次從服務器端下載完以后,它的使命就完成了。

那么有沒有辦法讓ajax和razor這兩種截然不同的技術有機地結合在一起呢?

最近本人在做一個項目時發現,只需要簡單的寫一個jquery的擴展,就可以實現上述目的。

 

先看下效果:

1. 當我們在vs2013下,新建一個asp.net mvc應用程序, 會出現一個初始站點,我們就在這個初始站點上做文章,

2. 把其中的“關於”和“聯系方式”兩個頁面,不導航到新頁面,直接在主頁原有的大屏幕介紹底下(如圖所示局部加載區)打開:

為實現這個效果,原有的服務器端的Controller中的邏輯不需要做任何的改變。也不需要對視圖做任何的改變。

改變的只是一個模板頁_Layout.cshtml。

原有的_Layout.cshtml的源代碼變成這樣:

 

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - 我的 ASP.NET 應用程序</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")

</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("應用程序名稱", "Index", "Home", null, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("主頁", "Index", "Home")</li>
                    <li>@Html.ActionLink("關於", "About", "Home")</li>
                    <li>@Html.ActionLink("聯系方式", "Contact", "Home")</li>
                </ul>
                @Html.Partial("_LoginPartial")
            </div>
        </div>
    </div>
    <div class="container body-content">
 <div id="partial"> @RenderBody() @RenderSection("innerScripts", required: false) </div>         <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - 我的 ASP.NET 應用程序</p>
        </footer>
    </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") <script type="text/javascript" src="~/Scripts/loadpartial.js"></script> <script type="text/javascript"> $.loadPartial({ link: '.nav a', container: '#partial' }); </script>
}</body>
</html>

 

 其中紅色加粗是加的代碼。 注意到有一個loadpartial.js文件。這就是對jquery作的一個小擴展。

調用方法是:       $.loadPartial({ link: '.nav a', container: '#partial' });

link代表一批鏈接的選擇器,container代表頁面加載到的容器。

注意: 所有加載的頁面到容器內時,不會加載和主頁重復的內容,如導航,版權聲明(如果那樣就太失敗了).只會加載自己的#partial中的內容。

如果加載的頁面在加載時有js要執行,可以寫在innerScripts這個區域中。

另外,如果加載進的頁面本身也有超鏈接,它依然會限制在這個框框內,more, 如果頁面有表單,表單的提交也會限制在這個框框內;

更有,如果你的后台程序出了BUG,比如404或500錯誤,它也會忠實地把錯誤信息像普通頁面一樣顯示在框框中。

看起來的感覺就像是一個內框架,但並不會破壞原有頁面的dom結構。

是不是很神奇?

而這個神奇只是jquery的功勞,我只是對它寫了幾十行的小擴展:

 

好了,上核心loadpartial.js文件的代碼:

/* Parital Load
(C) Copy right bwangel 2014
*/
jQuery.extend({
    /*
       局部加載頁
       options{
        link : 超鏈接的選擇器
        container: 要將頁面加載到的容的選擇器
        updateNow: 是否立即將容器中的現有鏈接進行處理
       }
    */
    loadPartial: function (options) {
        var defaults = { link: '.nav a', container: '#razorContainer', updateNow: true };
        defaults = $.extend(defaults, options);
        razorContainer = $(defaults.container);

        $(defaults.link).each(alink);

        if (defaults.updateNow) alinkInContainer();

        //var razorUrl = "";
        function alink(idx, link) {
            if ($(link).attr("onclick")) return;
            if (link.href.indexOf('###') >= 0) return;
            var addr1 = link.href.split('#');
            var addr2 = location.href.split('#');
            if (addr1[0] == addr2[0]) return; //說明是錨點跳轉

            $(link).click(function (e) {
                e.preventDefault();
                if ($(link).attr("action")) {
                    ConfirmDelete(link);
                } else {
                    getRazor(link.href, null, 'get');
                }
            });
        }

        function alinkInContainer() {
            razorContainer.find('a').each(alink);
            razorContainer.find('form').submit(function (e) {
                e.preventDefault();
                getRazor(this.action, $(this).serialize(), "post");
            });
        }

        function getRazor(url, d, m) {
            $.ajax({
                url: url,
                data: d,
                cache: false,
                type: m,
                success: function (data) {
                    var r = $("<div>").append($.parseHTML(data, true)).find('#partial');
                    razorContainer.html(r);
                    alinkInContainer();
                },
                error: function (response, status, xhr) {
                    razorContainer.html(response.responseText);
                }
            });
        }
    }
});

 

 關於此文的完整代碼,請在https://git.oschina.net/bwangel/LoadPartDemo下載

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM