母版頁(佈局頁)視圖

一、母版頁介紹和使用

母版頁的擴展名爲".cshtml",也叫做視圖佈局頁,它相當於網頁的模板。在其他網頁中,只要引用了母版頁,母版頁的頁面內容就可以自動顯示出來,設計者可以修改引用的母版頁中預留的部分,其他部分保持不變,這樣就可以使多個頁面的風格保持一致,給網頁設計帶來了很大的方便。

1、創建母版頁視圖的要點

(1)、在Views的子文件夾Shared文件夾裏面添加。

(2)、以“_”前綴作爲開頭。

(3)、以"Layout.cshtml"作爲結束。

2、MVC母版頁裏的三個功能點:

(1)、RenderBody-子頁面內容佔位符。

(2)、RenderPage-引用呈現一個頁面。

(3)、RenderSection-內容佔位符。

如果新建一個MVC程序,裏面有沒有使用母版頁視圖呢?查看Index視圖:

從上面的截圖中可以看出,Index裏面只有兩個DIV,但是一個基本的網頁代碼需要有HTML、head、body等元素標籤組成,但是這裏面並沒有。同時,瀏覽index視圖:

這時查看網頁源代碼:

從上面的截圖中可以看到有HTML、head、body等HTML元素,到這裏可以看出,MVC中已經使用了母版頁。MVC中默認使用Shared文件夾裏面的_ViewStart.cshtml視圖。

二、RenderBody

**RenderBody的作用是子頁面內容佔位符。即母版頁中使用了RenderBody的地方會使用子頁面的內容來代替**。以_Layout視圖爲例:

_TestLayout.cshtml
在這裏插入圖片描述

Test.cshtml 頁面

在這裏插入圖片描述

結果:
在這裏插入圖片描述
頁面還繼承了 _viewStart.cshtml
在這裏插入圖片描述

在_Layout母版頁中使用了RenderBody,所以運行的時候這部分內容將會被Index裏面的內容代替。

下面我們自己重新定義一個母版頁,同時定義一個子頁面來使用這個母版頁來查看RenderBody的作用。

1、添加母版頁

在Shared文件夾上面右鍵添加,選擇MVC5佈局頁

2、命名爲_TestLayout

生成的模板頁代碼如下:

複製代碼
<!DOCTYPE html>

<html>
<head>
<meta name=“viewport” content=“width=device-width” />
<title>@ViewBag.Title</title>
</head>
<body>
<div>
@RenderBody()
</div>
</body>
</html>

複製代碼

 3、修改母版頁,修改後的母版頁代碼如下:

複製代碼
<!DOCTYPE html>

<html>
<head>
<meta name=“viewport” content=“width=device-width” />
<title>@ViewBag.Title</title>
</head>
<body>
<div>
我是母版頁,在子頁面中不允許更改
<!–內容頁佔位符–>
@RenderBody()
</div>
</body>
</html>

複製代碼

 4、創建子頁面使用母版頁

在Home控制器裏面添加一個ActionName爲Test的Action方法,並添加視圖:

生成的Test視圖如下圖所示:

注意:如果Layout=null,則表示不使用母版頁視圖。

修改Test視圖也,修改後的代碼如下:

複製代碼
@{
    ViewBag.Title = "Test";
    Layout = "~/Views/Shared/_TestLayout.cshtml";
}

<h2>Test</h2>
<div>
我是子頁面-home控制器的Test方法
</div>

複製代碼

 5、運行程序,瀏覽Test視圖

通過運行結果和查看網頁源代碼,可以看出是母版頁和子頁面組成的頁面。

三、RenderPage

RenderPage:引用呈現一個頁面,即在一個頁面中引用呈現另外一個頁面,也就是說另外一個頁面是這個頁面的一部分。

以網頁尾部佈局爲例說明RenderPage。

1、在Shared文件夾裏面新添加一個分部頁,並命名爲FooterPartial。

2、修改分部也

修改後的代碼如下:

<div>
    我是頁腳
</div>

 

3、在母版頁中使用分部頁

在RenderBody的下面使用RenderPage,RenderPage方法的參數如下圖所示:

從上圖中可以看出,使用RenderPage()方法的時候,只需知道分部頁的路徑即可,修改後的母版頁代碼如下:

複製代碼
<!DOCTYPE html>

<html>
<head>
<meta name=“viewport” content=“width=device-width” />
<title>@ViewBag.Title</title>
</head>
<body>
<div>
我是母版頁,在子頁面中不允許更改
<!–內容頁佔位符–>
@RenderBody()
@RenderPage("_FooterPartial.cshtml")
</div>
</body>
</html>

複製代碼

 

4、運行結果

四、RenderSection

先來看下面一個例子:

在Test視圖裏面添加一段腳本,修改後的Test視圖代碼如下:

這是在運行程序,結果如下:

通過運行結果發現腳本在視圖內容呈現之前先執行了,這顯示不是我們想要的效果。我們希望是在整個頁面都加載完成之後再執行腳本。修改佈局頁代碼如下:

複製代碼
<!DOCTYPE html>

<html>
<head>
<meta name=“viewport” content=“width=device-width” />
<title>@ViewBag.Title</title>
</head>
<body>
<div>
我是母版頁,在子頁面中不允許更改
<!–內容頁佔位符–>
@RenderBody()
<div style=“color:blue”>
<p>
<!---->
@RenderSection(“SectionContent”)
</p>
</div>
@RenderPage("_FooterPartial.cshtml")
</div>

</body>

</html>

複製代碼

 

子頁面修改如下:

運行結果:

如果在母版頁中定義了RenderSection,而在子頁面中並沒有對定義的RenderSection進行處理,那麼結果是怎樣的呢?

從上圖中可以看出,如果在子頁面中沒有對定義的RenderSection進行處理,程序運行的時候直接就報錯了:SectionContent節未定義。如果不想處理RenderSection該如何修改呢?

RenderSection方法截圖如下:

如果不想處理RenderSection,那麼required參數設置爲false就可以了,修改後的佈局頁代碼如下:

複製代碼
<!DOCTYPE html>

<html>
<head>
<meta name=“viewport” content=“width=device-width” />
<title>@ViewBag.Title</title>
</head>
<body>
<div>
我是母版頁,在子頁面中不允許更改
<!–內容頁佔位符–>
@RenderBody()
<div style=“color:blue”>
<p>
<!---->
@RenderSection(“SectionContent”,false)
</p>
</div>
@RenderPage("_FooterPartial.cshtml")
</div>

</body>

</html>

複製代碼

 這時在運行程序就可以正常運行了。

通過上面的例子,我們可以使用下面的方法解決開頭例子中遇到的問題:在body元素的結束標籤上面定義RenderSection,這時無論在子頁面的任何位置定義script腳本,都會在頁面全部加載完成以後才執行腳本。

佈局頁定義如下:

五、總結

1、RenderBody

在Razor引擎中沒有“母版頁”,取而代之的是叫做“佈局”的頁面(_Layout.cshtml)放在了共享視圖文件夾中。在這個頁面中,會看到標籤裏面有這樣一條語句:
@RenderBody()
其實它的作用和母版頁中的服務器控件類似,當創建基於此佈局頁面的視圖時,視圖的內容會和佈局頁面合併,而新創建視圖的內容會通過佈局頁面的@RenderBody()方法呈現在標籤之間。
這個方法不需要參數,而且只能出現一次。

2、RenderPage

從名稱可以猜出來這個方法是要呈現一個頁面。比如網頁中固定的頭部可以單獨放在一個共享的視圖文件中,然後在佈局頁面中通過這個方法調用,用法如下:
@RenderPage("_FooterPartial.cshtml")
可以帶參數
@RenderPage("_FooterPartial.cshtml",new {parm="my",parm2="you"})
調用頁面獲取參數:
//獲取RenderPage()傳遞過來的參數
@PageData["param"]

3、RenderSection

佈局頁面還有節(Section)的概念,也就是說:如果某個視圖模板中定義了一個節,那麼可以把它單獨呈現出來,用法如下:
@RenderBody()
@RenderPage("_FooterPartial.cshtml")
//模板裏添加了一個節
@RenderSection("head")
當然還要在視圖中定義節,否則會出現異常:
@secion head{
//do
}
爲了防止因缺少節而出現異常,可以給RenderSection()提供第2個參數:
@RenderSection("head",false)
或者
@if(IsSectionDefined("head"))
{
@RenderSection("head",false)
}
else
{
<p>head Section is not defined!</p>
}

4、@Html.Partial

Partial每次都會創建自己的TextWriter實例並且把內容緩存到內存中,最後把所有write輸出的內容發送到一個MvcString對象中。
更多時候我們會使用@{Html.RenderPartial("Details");}而不是@Html.Partial。
Html.RenderPartial()和@Html.Partial的區別:
Html.RenderPartial()直接輸出至當前HttpContext(因爲是直接輸出,所以性能好)。
Html.Partial 將視圖內容直接生成一個字符串並返回(相當於有個轉義的過程)。
RenderPage()和RenderPartial()的區別
RenderPage()調用的頁面只能使用其傳遞過去的數據。
RenderPartial()是可以使用ViewData、model等數據的。
如:@{Html.RenderPartial("BasicChart",model);}
用這個重載可以在部分視圖裏使用強類型,然後在主視圖中使用第二個參數傳model過去。
@{Html.RenderPartial("BasicChart",ViewData["myData"]);}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章