<input id="ohw05"></input>
  • <table id="ohw05"><menu id="ohw05"></menu></table>
  • <var id="ohw05"></var>
  • <code id="ohw05"><cite id="ohw05"></cite></code>
    <label id="ohw05"></label>
    <var id="ohw05"></var>
  • 基于.NetCore開發博客項目 StarBlog - (7) 頁面開發之文章詳情頁面

    系列文章

    前言

    前一篇博客完成了文章列表的開發,現在要來寫文章詳情頁面了(這篇更新應該沒遲到吧,嘿嘿)

    博客網站最重要的可以說就是文章詳情頁面了,用戶來看博客最關心首先是內容,其次是閱讀體驗,所以這個文章詳情頁面的設計不能馬虎~

    思路

    文章正文是以markdown格式存儲的,要在網頁上展示的話,需要把markdown渲染成HTML才行。

    那么就有兩種思路:

    • 一種是在后端渲染,使用C#把markdown轉換成HTML然后渲染成網頁
    • 另一種是后端直接輸出markdown,使用一些開源的JS庫實現markdown渲染

    一開始我是采用第一種的后端渲染方式,用到的C#庫是Markdig,不過深入使用之后發現有一些想要的功能實現起來比較麻煩,特別是這個庫幾乎沒有文檔,要自定義一些功能全靠看源碼+猜,最后只能放棄轉而使用第二種方式。

    本文對兩種方式的實現都會介紹,著重介紹第二種前端渲染。

    后端渲染

    關于Markdig這個庫的我之前寫的博客有詳細的介紹,這里不再重復,有興趣的同學可以看看:C#解析Markdown文檔,實現替換圖片鏈接操作

    首先Nuget安裝Markdig這個庫

    一行代碼就可以實現markdown轉HTML

    Markdig.Markdown.ToHtml(markdownContent);
    

    當然直接渲染出來的頁面是很簡陋的,沒有代碼高亮、沒有引用塊、沒有列表樣式啥的,所以單純這樣肯定是不夠的。

    Markdig作為C#目前唯一積極維護的Markdown庫,自然是考慮到了擴展性,它設計了擴展系統,本身內置了20多個擴展,還可以安裝其他人開發的擴展用來實現例如代碼高亮的效果。

    使用擴展也很簡單,加個pipeline參數就行

    var pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build();
    var result = Markdown.ToHtml("This is a text with some *emphasis*", pipeline);
    

    Markdig本身不自帶代碼高亮擴展,需要使用第三方組件,我測試了下面這兩個能用

    前端渲染

    本項目最終選了前端渲染的方案,前端生態有眾多的markdown組件,看了一圈之后我最終選了Editor.md這個組件。

    主要看中它可以比較方便的實現文章的TOC(目錄)功能,還有不錯的高亮效果。

    使用起來很簡單

    首先把markdown輸出到網頁里

    <div id="test-editormd-view" class="post-content">
        <textarea id="append-test" style="display:none;">@Model.Content</textarea>
    </div>
    

    加了display:none不顯示這個textarea,給用戶看markdown代碼沒用

    引入edtor.md的樣式文件

    <link rel="stylesheet" href="~/lib/editormd/css/editormd.preview.min.css">
    

    引入editor.md的js,你沒看錯,就是這么多。靜態資源在之前的文章里已經安裝好了,這里不再重復。詳見:(5) 開始搭建Web項目

    <script src="~/lib/editormd/examples/js/jquery.min.js"></script>
    <script src="~/lib/editormd/lib/marked.min.js"></script>
    <script src="~/lib/editormd/lib/prettify.min.js"></script>
    
    <script src="~/lib/editormd/lib/raphael.min.js"></script>
    <script src="~/lib/editormd/lib/underscore.min.js"></script>
    <script src="~/lib/editormd/lib/sequence-diagram.min.js"></script>
    <script src="~/lib/editormd/lib/flowchart.min.js"></script>
    <script src="~/lib/editormd/lib/jquery.flowchart.min.js"></script>
    
    <script src="~/lib/editormd/editormd.min.js"></script>
    

    然后,使用js調用editor.md的渲染方法

    let testEditormdView = editormd.markdownToHTML("test-editormd-view", {
        // htmlDecode: "style,script,iframe",  // you can filter tags decode
        htmlDecode: true,
        //toc             : false,
        tocm: true,    // Using [TOCM]
        tocContainer: "#custom-toc-container", // 自定義 ToC 容器層
        //gfm             : false,
        //tocDropdown     : true,
        // markdownSourceCode : true, // 是否保留 Markdown 源碼,即是否刪除保存源碼的 Textarea 標簽
        emoji: true,
        taskList: true,
        tex: true,  // 默認不解析
        flowChart: true,  // 默認不解析
        sequenceDiagram: true,  // 默認不解析
    })
    

    搞定。

    ViewModel

    Post模型只是存在數據庫中的數據,直接展示不能完全滿足網頁設計的需求,所以還是一樣,需要定義一個ViewModel來用。

    依然是放在StarBlog.Web/ViewModels

    代碼如下

    public class PostViewModel {
        public string Id { get; set; }
        public string Title { get; set; }
        public string Summary { get; set; }
        public string Content { get; set; }
        public string ContentHtml { get; set; }
        public string Path { get; set; }
        public DateTime CreationTime { get; set; }
        public DateTime LastUpdateTime { get; set; }
        public Category Category { get; set; }
        public List<Category> Categories { get; set; }
    }
    

    相比起Post模型,多了ContentHtmlCategories改成列表

    Service

    關鍵的渲染部分介紹完了,講一下一些次要的~

    Service的作用是把Post模型轉換成ViewModel

    那直接上代碼吧

    public PostViewModel GetPostViewModel(Post post) {
        var vm = new PostViewModel {
            Id = post.Id,
            Title = post.Title,
            Summary = post.Summary,
            Content = post.Content,
            ContentHtml = Markdig.Markdown.ToHtml(post.Content),
            Path = post.Path,
            CreationTime = post.CreationTime,
            LastUpdateTime = post.LastUpdateTime,
            Category = post.Category,
            Categories = new List<Category>()
        };
    
        foreach (var itemId in post.Categories.Split(",").Select(int.Parse)) {
            var item = _categoryRepo.Where(a => a.Id == itemId).First();
            if (item != null) vm.Categories.Add(item);
        }
    
        return vm;
    }
    

    雖然不用后端渲染方案,不過我還是保留了Markdig的后端渲染。

    View

    PS:Controller部分被我略過了,實在是太簡單,沒必要貼代碼了

    這個好像也沒啥好介紹的,那還是不貼完整代碼了,詳細代碼在這:https://github.com/Deali-Axy/StarBlog/blob/master/StarBlog.Web/Views/Blog/Post.cshtml

    使用Bootstrap的Grid布局做左右兩欄,左欄顯示文章的TOC目錄,右欄顯示文章的主體內容。

    頁面頂部要展示分類的層級關系,不同分類之間用“/”分隔,但第一個分類前面不要有斜杠(復雜的表述方式)

    這個需求的實現代碼是這樣

    <div>
        分類:
        @foreach (var category in Model.Categories) {
        @if (Model.Categories.IndexOf(category) > 0) {
        <span> / </span>
        }
        <a asp-controller="Blog" asp-action="List"
           asp-route-categoryId="@category.Id">
            @category.Name
        </a>
        }
    </div>
    

    效果大概這樣:

    image

    然后還要優化一下時間的顯示

    @Model.LastUpdateTime.ToShortDateString()
    @Model.LastUpdateTime.ToString("hh:mm")
    

    完成之后的效果如下

    實現效果

    image

    大概就是這樣,后續可能會再優化一下頁面。

    搞定~

    posted @ 2022-05-20 18:01  程序設計實驗室  閱讀(344)  評論(0編輯  收藏  舉報
    国产美女a做受大片观看