上篇文章咱們完成了 動態生成多級菜單 這個實用組件。 html
本篇文章咱們要開發另外一個實用組件:麪包屑導航。 前端
麪包屑導航(BreadcrumbNavigation)這個概念來自童話故事"漢賽爾和格萊特",當漢賽爾和格萊特穿過森林時,不當心迷路了,可是他們發如今沿途走過的地方都撒下了麪包屑,讓這些麪包屑來幫助他們找到回家的路。因此,麪包屑導航的做用是告訴訪問者他們目前在網站中的位置以及如何返回。(摘自百度百科) 後端
要實現麪包屑導航,也能夠直接從nuget搜一些sitemap組件直接使用。 學習
固然,和上篇同樣,咱們一樣不用任何第三方組件,徹底本身構建靈活通用的sitemap. 網站
下面給出個人最佳實踐。 ui
1、分析多級目錄的html結構 url
2、根據html結構構建xml的站點地圖源及相應的data model spa
3、構建html helper, 完成breadcrumb生成功能 3d
4、前端調用 orm
實現麪包屑導航分紅兩個步驟:
1. 獲取當前的url地址,根據url地址去相關配置文件中查詢到當前位置,遞歸查詢父節點
2. 根據查詢到的結果動態拼接出 breadcrumb 的html
若是你們看了上篇文章應該會對這篇文章用到的技術很熟悉(比上篇文章更簡單 : ))
咱們直接根據站點的配置拼接出 html,前端經過自定義html helper的方法調用獲取拼接出的內容。
關於如何自定義html helper,上篇文章有介紹,再也不重複。
下面直接講解詳細步驟。
分紅四個步驟
首先打開一個樣例,以下圖
對應的html爲
你們能夠看到,由兩層組成, 外面是一個<ol>, 裏面是一組<li>。
每一個<li>包含一個<a>標籤,指向相應的位置地址。
最後的<li>不包含<a>標籤,僅顯示名字。
1. 根據上面的html結構,咱們準備站點地圖的數據源。
通常來講,站點地圖不涉及到權限,也不會常常改變,如網站的某個位置沒有配置,直接不顯示便可,也不會有其餘影響。
所以咱們簡單起見,直接準備個xml文檔便可。
<?xml version="1.0" encoding="utf-8" ?>
<!--填絕對路徑,相似 /XEngine/home/about-->
<MvcSiteMaps>
<MvcSiteMap ParnetID = "0" Name = "主頁" Url = "/XEngine/" ID = "1" ></MvcSiteMap>
<MvcSiteMap ParnetID = "1" Name = "組織" Url = "/XEngine/Organization" ID = "2"></MvcSiteMap>
<MvcSiteMap ParnetID = "2" Name = "關於" Url = "/XEngine/home/about" ID = "3"></MvcSiteMap>
</MvcSiteMaps>
最終咱們只須要將xml中相應的值填充到breadcrumb的html
2. 準備對應的data model
[XmlRoot("MvcSiteMaps")]
public class MvcSiteMaps
{
[XmlElement("MvcSiteMap")]
public MvcSiteMap[] Items { get; set; }
}
public class MvcSiteMap
{
[XmlAttribute(AttributeName = "ID")]
public int ID { get; set; }
[XmlAttribute(AttributeName = "Name")]
public string Name { get; set; }
[XmlAttribute(AttributeName = "Url")]
public string Url { get; set; }
[XmlAttribute(AttributeName = "ParnetID")]
public int ParnetID { get; set; }
public MvcSiteMap Parent { get; set; }
}
注意 [XmlAttribute(AttributeName = "xxx")],AttributeName須要和xml裏面的名字對應,咱們的xml和data model的命名徹底對應,因此也能夠省略。
須要完成如下幾個功能
1. 獲取xml中全部的節點信息
private static string SiteMapString = System.Configuration.ConfigurationManager.AppSettings["SiteMapString"] ?? string.Empty;
//獲取sitemap的配置信息
public static IList<MvcSiteMap> GetSiteMapList()
{
using (TextReader reader = new StreamReader(HttpContext.Current.Server.MapPath(SiteMapString)))
{
var serializer = new XmlSerializer(typeof(MvcSiteMaps));
var items = (MvcSiteMaps)serializer.Deserialize(reader);
if (items != null)
{
return items.Items;
}
return null;
}
}
2. 根據上一步獲取的節點信息及當前url地址,拼接出麪包屑html
/// <summary>
/// 填充麪包屑
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static MvcHtmlString PopulateBreadcrumb(string url)
{
StringBuilder str = new StringBuilder();
List<string> pathList = new List<string>();
MvcSiteMap current = GetSiteMapList().FirstOrDefault(m=>m.Url==url);
GetParent(current, pathList);
pathList.Reverse();
for (int i = 0; i < pathList.Count; i++)
{
if (i == pathList.Count - 1)
{
string s = pathList[i];
s = s.Substring(s.IndexOf(">") + 1, s.LastIndexOf("<") - s.IndexOf(">") - 1);
str.AppendFormat("<li class='active'>{0}</li>", s);
}
else
{
str.AppendFormat("<li>{0}</li>", pathList[i]);
}
}
string result = str.ToString();
return MvcHtmlString.Create(result);
}
說明:首先找到當前位置,遞歸找出父節點依次添加到列表中;反轉列表,完善html代碼。
/// <summary>
/// 遞歸找到上一級
/// </summary>
/// <param name="parent"></param>
/// <param name="pathList"></param>
static void GetParent(MvcSiteMap parent, List<string> pathList)
{
if (parent != null)
{
pathList.Add(string.Format("<a href={0}>{1}</a>", parent.Url, parent.Name));
parent.Parent = GetSiteMapList().FirstOrDefault(i => i.ID == parent.ParnetID);
GetParent(parent.Parent, pathList);
}
}
相似於上一篇文章,咱們新建個html helper供前端調用。
此次咱們稍微作一點改進(規範一下命名)
先看下微軟原生的html helper定義方法,以Html.ActionLink爲例,以下圖
如方框處,相似於 xxxExtensions的命名,咱們定義一個靜態類來調用以前的方法。
前端調用:
以訪問http://localhost/XEngine/home/about 爲例,最終返回的結果
相應的html爲:
<div>
<br />
<ol class="breadcrumb">
<li><a href=/XEngine/>主頁</a></li><li><a href=/XEngine/Organization>組織</a></li><li class='active'>關於</li>
</ol>
</div>
本篇對上篇的用到的html helper知識點作了細微改進 :
規範了自定義 html helper命名(類名爲xxxExtensions和,原生形式統一);
直接返回MvcHtmlString類型,這樣html字符串不會被轉義,能夠直接在前端調用。
自定義的 html helper很是實用,你們能夠多多挖掘使用場景。
歡迎你們多多評論,祝學習進步:)
P.S.
示例中前端直接在_Layout.cshtml中使用。
後端菜單相關的程序結構: