<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Loading

      基于.NetCore開(kāi)發(fā)博客項(xiàng)目 StarBlog - (7) 頁(yè)面開(kāi)發(fā)之文章詳情頁(yè)面

      系列文章

      前言

      前一篇博客完成了文章列表的開(kāi)發(fā),現(xiàn)在要來(lái)寫(xiě)文章詳情頁(yè)面了(這篇更新應(yīng)該沒(méi)遲到吧,嘿嘿)

      博客網(wǎng)站最重要的可以說(shuō)就是文章詳情頁(yè)面了,用戶(hù)來(lái)看博客最關(guān)心首先是內(nèi)容,其次是閱讀體驗(yàn),所以這個(gè)文章詳情頁(yè)面的設(shè)計(jì)不能馬虎~

      思路

      文章正文是以markdown格式存儲(chǔ)的,要在網(wǎng)頁(yè)上展示的話(huà),需要把markdown渲染成HTML才行。

      那么就有兩種思路:

      • 一種是在后端渲染,使用C#把markdown轉(zhuǎn)換成HTML然后渲染成網(wǎng)頁(yè)
      • 另一種是后端直接輸出markdown,使用一些開(kāi)源的JS庫(kù)實(shí)現(xiàn)markdown渲染

      一開(kāi)始我是采用第一種的后端渲染方式,用到的C#庫(kù)是Markdig,不過(guò)深入使用之后發(fā)現(xiàn)有一些想要的功能實(shí)現(xiàn)起來(lái)比較麻煩,特別是這個(gè)庫(kù)幾乎沒(méi)有文檔,要自定義一些功能全靠看源碼+猜,最后只能放棄轉(zhuǎn)而使用第二種方式。

      本文對(duì)兩種方式的實(shí)現(xiàn)都會(huì)介紹,著重介紹第二種前端渲染。

      后端渲染

      關(guān)于Markdig這個(gè)庫(kù)的我之前寫(xiě)的博客有詳細(xì)的介紹,這里不再重復(fù),有興趣的同學(xué)可以看看:C#解析Markdown文檔,實(shí)現(xiàn)替換圖片鏈接操作

      首先Nuget安裝Markdig這個(gè)庫(kù)

      一行代碼就可以實(shí)現(xiàn)markdown轉(zhuǎn)HTML

      Markdig.Markdown.ToHtml(markdownContent);
      

      當(dāng)然直接渲染出來(lái)的頁(yè)面是很簡(jiǎn)陋的,沒(méi)有代碼高亮、沒(méi)有引用塊、沒(méi)有列表樣式啥的,所以單純這樣肯定是不夠的。

      Markdig作為C#目前唯一積極維護(hù)的Markdown庫(kù),自然是考慮到了擴(kuò)展性,它設(shè)計(jì)了擴(kuò)展系統(tǒng),本身內(nèi)置了20多個(gè)擴(kuò)展,還可以安裝其他人開(kāi)發(fā)的擴(kuò)展用來(lái)實(shí)現(xiàn)例如代碼高亮的效果。

      使用擴(kuò)展也很簡(jiǎn)單,加個(gè)pipeline參數(shù)就行

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

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

      前端渲染

      本項(xiàng)目最終選了前端渲染的方案,前端生態(tài)有眾多的markdown組件,看了一圈之后我最終選了Editor.md這個(gè)組件。

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

      使用起來(lái)很簡(jiǎn)單

      首先把markdown輸出到網(wǎng)頁(yè)里

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

      加了display:none不顯示這個(gè)textarea,給用戶(hù)看markdown代碼沒(méi)用

      引入edtor.md的樣式文件

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

      引入editor.md的js,你沒(méi)看錯(cuò),就是這么多。靜態(tài)資源在之前的文章里已經(jīng)安裝好了,這里不再重復(fù)。詳見(jiàn):(5) 開(kāi)始搭建Web項(xiàng)目

      <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調(diào)用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 標(biāo)簽
          emoji: true,
          taskList: true,
          tex: true,  // 默認(rèn)不解析
          flowChart: true,  // 默認(rèn)不解析
          sequenceDiagram: true,  // 默認(rèn)不解析
      })
      

      搞定。

      ViewModel

      Post模型只是存在數(shù)據(jù)庫(kù)中的數(shù)據(jù),直接展示不能完全滿(mǎn)足網(wǎng)頁(yè)設(shè)計(jì)的需求,所以還是一樣,需要定義一個(gè)ViewModel來(lái)用。

      依然是放在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

      關(guān)鍵的渲染部分介紹完了,講一下一些次要的~

      Service的作用是把Post模型轉(zhuǎn)換成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;
      }
      

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

      View

      PS:Controller部分被我略過(guò)了,實(shí)在是太簡(jiǎn)單,沒(méi)必要貼代碼了

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

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

      頁(yè)面頂部要展示分類(lèi)的層級(jí)關(guān)系,不同分類(lèi)之間用“/”分隔,但第一個(gè)分類(lèi)前面不要有斜杠(復(fù)雜的表述方式)

      這個(gè)需求的實(shí)現(xiàn)代碼是這樣

      <div>
          分類(lèi):
          @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

      然后還要優(yōu)化一下時(shí)間的顯示

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

      完成之后的效果如下

      實(shí)現(xiàn)效果

      image

      大概就是這樣,后續(xù)可能會(huì)再優(yōu)化一下頁(yè)面。

      搞定~

      posted @ 2022-05-20 18:01  程序設(shè)計(jì)實(shí)驗(yàn)室  閱讀(1096)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 50路熟女| 成人av午夜在线观看| 国语精品一区二区三区| 99riav精品免费视频观看| 人妻少妇精品无码专区二区| 人妻精品动漫H无码中字| 国产普通话对白刺激| 国产成人综合网亚洲第一| 久久中文字幕一区二区| 国产伦人人人人人人性| 久久老熟妇精品免费观看| 精品无码国产不卡在线观看| 日韩熟妇中文色在线视频| 国产h视频在线观看| 久久欧洲精品成av人片| 91老熟女老人国产老太| 国产99视频精品免费视频36| 国产网红女主播精品视频| 亚洲国产一区二区三区久| 亚洲熟妇AV午夜无码不卡| 久久国产乱子精品免费女| 国产自拍在线一区二区三区| 人妻在线无码一区二区三区| 久久大香萑太香蕉av黄软件| 精品一区二区亚洲国产| 国产明星精品无码AV换脸| 久久久久青草线综合超碰| 亚洲成人精品综合在线| 亚洲综合久久精品哦夜夜嗨| 熟妇人妻av无码一区二区三区| 亚洲成av人片天堂网| 国产精品无码无在线观看| 国内少妇偷人精品免费| 日韩日韩日韩日韩日韩熟女| 精品乱人伦一区二区三区| 老熟女多次高潮露脸视频| 不卡AV中文字幕手机看| 国产精品视频第一第二区| 韩国三级+mp4| 欧美日韩中文字幕视频不卡一二区| 亚洲男女羞羞无遮挡久久丫|