Vue + WebApi 小項目:構造自己的線上 Markdown 筆記本應用

来源:https://www.cnblogs.com/liqingwen/archive/2019/01/14/10264626.html
-Advertisement-
Play Games

Vue + WebApi 小項目:構造自己的線上 Markdown 筆記本應用 目錄 概要 知識點 完整示例圖 代碼與資源文件 流程步驟 概要 基於 MVP 最小可行性產品設計理念,我們先完成一個可以使用,並具備基本功能的 Markdown 筆記本應用,再進行逐步完善。 知識點 本文會指導初學者如何 ...


Vue + WebApi 小項目:構造自己的線上 Markdown 筆記本應用

目錄

  • 概要
  • 知識點
  • 完整示例圖
  • 代碼與資源文件
  • 流程步驟

 

概要

  基於 MVP 最小可行性產品設計理念,我們先完成一個可以使用,並具備基本功能的 Markdown 筆記本應用,再進行逐步完善。

 

知識點

  本文會指導初學者如何一步步運用 Vue 的計算屬性、雙向綁定、指令、生命周期鉤子,還有 localStorage 和非同步請求等知識點。

 

完整示例圖

   

代碼與資源文件

   https://github.com/liqingwen2015/MarkdownDemo

  為了避免網路原因造成的問題,文中所使用的第三方庫(可自己去官方下載最新版,文章使用的是當前發佈時間最新版本的 js 文件)以及 css 文件都下載好並且已經放入裡面。

body {
    font-family: sans-serif;
    font-size: 16px;
    height: 100%;
    margin: 0;
    box-sizing: border-box;
  }
  
  .material-icons {
    font-size: 24px;
    line-height: 1;
    vertical-align: middle;
    margin: -3px;
    padding-bottom: 1px;
  }
  
  #app > * {
    float: left;
    display: flex;
    flex-direction: column;
    height: 100%;
  
    > * {
      flex: auto 0 0;
    }
  }
  
  .side-bar {
    background: #f8f8f8;
    width: 20%;
    box-sizing: border-box;
  }
  
  .note {
    padding: 16px;
    cursor: pointer;
  }
  
  .note:hover {
    background: #ade2ca;
  }
  
  .note .icon {
    float: right;
  }
  
  button,
  input,
  textarea {
    font-family: inherit;
    font-size: inherit;
    line-height: inherit;
    box-sizing: border-box;
    outline: none !important;
  }
  
  button,
  .note.selected {
    background: orange;
    color: white;
  }
  
  button {
    border-radius: 3px;
    border: none;
    display: inline-block;
    padding: 8px 12px;
    cursor: pointer;
  }
  
  button:hover {
    background: #63c89b;
  }
  
  input {
    border: solid 2px #ade2ca;
    border-radius: 3px;
    padding: 6px 10px;
    background: #f0f9f5;
    color: #666;
  }
  
  input:focus {
    border-color: orange;
    background: white;
    color: black;
  }
  
  button,
  input {
    height: 34px;
  }
  
  .main, .preview {
    width: 40%;
  }
  
  .toolbar {
    padding: 4px;
    box-sizing: border-box;
  }
  
  .status-bar {
    color: #999;
    font-style: italic;
  }
  
  textarea {
    resize: none;
    border: none;
    box-sizing: border-box;
    margin: 0 4px;
    font-family: monospace;
  }
  
  textarea, .notes, .preview {
    flex: auto 1 1;
    overflow: auto;
  }
  
  .preview {
    padding: 12px;
    box-sizing: border-box;
    border-left: solid 4px #f8f8f8;
  }
  
  .preview p:first-child {
    margin-top: 0;
  }
  
  a {
    color: orange;
  }
  
  h1,
  h2,
  h3 {
    margin: 10px 0 4px;
    color: orange;
  }
  
  h1 {
    font-size: 2em;
  }
  
  h2 {
    font-size: 1.5em;
  }
  
  h3 {
    font-size: 1.2em;
  }
  
  h4 {
    font-size: 1.1em;
    font-weight: normal;
  }
使用的 index.css 文件

 

流程步驟

  1.先構建一個基本的 html 文件,並引入核心 js 庫。

  這裡需要引入的第三方庫為 vue.js、marked.js。

<html>

<head>
    <title></title>
    <!-- 引入樣式文件 -->
    <link rel="stylesheet" href="index.css" />
</head>

<body>
    <!-- 引入 js 庫 -->
    <script src="/lib/vue.js"></script>
    <script src="/lib/marked.js"></script>

    <!-- js 代碼 -->
    <script src="index.js"></script>
</body>

</html>

 

  因為考慮到項目主要劃分為兩塊,左邊是書寫區域,右邊為預覽區域,<body> 塊代碼修改為:

<body>
    <!-- 引入 js 庫 -->
    <script src="lib/vue.js"></script>
    <script src="lib/marked.js"></script>

    <div id="app">
        <!-- 主區域:書寫 -->
        <section class="main"></section>

        <!-- 預覽區域 -->
        <aside class="preview"></aside>
    </div>

    <!-- js 代碼 -->
    <script src="index.js"></script>
</body>

 

  修改 js 代碼:創建 Vue 實例,並將其掛載到 DOM 元素上。

new Vue({
    el: '#app'
})

 

  【備註】上面的掛載方式是比較常見的一種,我們也可以使用 app.$mount('#app') 進行掛載。

 

  2.接下來我們使用 Vue 的雙向綁定機制控制輸入的內容和預覽的內容。

  修改 html:

<body>
    <!-- 引入 js 庫 -->
    <script src="lib/vue.js"></script>
    <script src="lib/marked.js"></script>

    <div id="app">
        <!-- 主區域:書寫 -->
        <section class="main">
            <textarea v-model="editor"></textarea>
        </section>

        <!-- 預覽區域 -->
        <aside class="preview">
            {{editor}}
        </aside>
    </div>

    <!-- js 代碼 -->
    <script src="index.js"></script>
</body>

 

  修改 js,增加數據屬性:

new Vue({
    el: '#app',
    data() {
        return {
            editor: '編輯器'
        }
    }
})

 

  現在,打開 index.html 頁面,在瀏覽器頁面中的左側進行輸入就可以在預覽視窗中同步看到輸入後的情況。

 

  3.接下來,我們需要對輸入的內容經過 Markdown 形式轉換,在這裡,我們使用 Vue 的計算屬性來進行優化渲染 Markdown 的實時預覽

  修改 js:

new Vue({
    // 掛載
    el: '#app',
    
    // 數據
    data() {
        return {
            editor: '編輯器'
        }
    },

    // 計算屬性
    computed: {
        editorPreview() {
            return marked(this.editor);
        }
    }
})

 

  修改 <body>,使用 v-html 指令取代 {{ }},以這種方式來渲染 HTML 元素。

<body>
    <!-- 引入 js 庫 -->
    <script src="lib/vue.js"></script>
    <script src="lib/marked.js"></script>

    <div id="app">
        <!-- 主區域:書寫 -->
        <section class="main">
            <textarea v-model="editor"></textarea>
        </section>

        <!-- 預覽區域 -->
        <aside class="preview" v-html="editorPreview"> </aside>
    </div>

    <!-- js 代碼 -->
    <script src="index.js"></script>
</body>

 

  運行效果圖

 

  4.保存內容

  目前,如果關閉了瀏覽器或者對頁面進行了刷新,所有內容都會丟失。所以,我們目前使用 localStorage  的方式進行數據的保存操作。

  現在產生了一個疑問:應該什麼時候進行保存呢?

  我們現在使用 Vue 的偵聽器功能來對數據的改動進行保存操作,因為它可以監聽到 editor 的每一改動操作,意思是每次輸入操作都會觸發偵聽器裡面的方法。

  修改 js:

new Vue({
    // 掛載
    el: '#app',

    // 數據
    data() {
        return {
            editor: '編輯器'
        }
    },

    // 計算屬性
    computed: {
        editorPreview() {
            return marked(this.editor);
        }
    },

    // 偵聽器
    watch: {
        editor(val) {
            localStorage.setItem('editor', this.editor);
        }
    }
})

 

  那麼現在又產生了新的疑問:應該怎樣才能夠在每次進入這個頁面時顯示之前保存的信息呢?

  現在,我們通過利用 Vue 的生命周期鉤子(目前使用 created 鉤子)來進行數據的讀取及恢復。

  修改 js:

new Vue({
    // 掛載
    el: '#app',

    // 數據
    data() {
        return {
            editor: '編輯器',
            key: {
                editor: 'editor'
            }
        }
    },

    // 計算屬性
    computed: {
        editorPreview() {
            return marked(this.editor);
        }
    },

    // 偵聽器
    watch: {
        editor(val) {
            localStorage.setItem(this.key.editor, this.editor);
        }
    },

    // 生命周期鉤子
    created() {
        this.editor = localStorage.getItem(this.key.editor) || '第一次使用 Markdown 筆記本';
    }
})

 

  【備註】在進行修改 js 後,editor 屬性第一次載入的時候可能為 null,這會導致整個應用出錯,所以這裡採用了預設值。

 

  5.localStorage 畢竟不是永久保存的方式,這裡我使用一種較為簡單的方式,保存方法替換為非同步請求到 WebApi 介面保存到資料庫的方式

  修改 html,引入 axios 庫:

<script src="lib/axios.min.js"></script>

 

  同時,修改 js,增加兩個 Http 請求的方法,獲取和保存:

new Vue({
    // 掛載
    el: '#app',

    // 數據
    data() {
        return {
            editor: '',
            key: {
                editor: 'editor'
            },
            url: 'http://localhost:34473/api/markdown'  // 需要替換成自己的 API 路徑
        }
    },

    // 計算屬性
    computed: {
        editorPreview() {
            return marked(this.editor);
        }
    },

    // 偵聽器
    watch: {
        editor(val) {
            //localStorage.setItem(this.key.editor, this.editor);
            this.save();
        }
    },

    // 生命周期鉤子
    created() {
        this.load();
        // this.editor = localStorage.getItem(this.key.editor) || '第一次使用 Markdown 筆記本';
    },

    // 方法
    methods: {
        load() {
            var that = this;
            axios.get(that.url).then(function (result) {
                console.log(result.data);
                that.editor = result.data;
            });
        },
        save() {
            var that = this;
            axios.post(that.url, { content: that.editor }).then(function (result) { });
        }
    }
})

 

  新增的 API 控制器 MarkdownController.cs 的內容如下:

    [Route("api/[controller]")]
    [ApiController]
    public class MarkdownController : ControllerBase
    {
        public static MarkdownViewModel MarkdownViewModel = new MarkdownViewModel()
        {
            Content = "我的第一個 Markdown 應用"
        };

        [HttpGet]
        public ActionResult<string> Get()
        {
            return MarkdownViewModel.Content;
        }

        [HttpPost]
        public void Save([FromBody] MarkdownViewModel vm)
        {
            MarkdownViewModel = vm;
        }
    }

 

  視圖模型 MarkdownViewModel.cs 的內容如下:

    public class MarkdownViewModel
    {
        public string Content { get; set; }
    }

 

  【備註】需要自行進行 WebApi 的跨域配置,演示時進行了忽略配置  

  【備註】示例代碼可從 https://github.com/liqingwen2015/MarkdownDemo 下載

 

【切換閱讀方式】https://www.jianshu.com/p/a17033ca91d9
【參考】Vue.js 2 Web Development Projects


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Exercise2是註釋和井號 Comments and Pound Characters 具體詳情請參考 "習題一" ,這裡就不在做過多的贅述。 習題 3: 數字和數學計算 學習目標: 瞭解Python中常用的算術運算符,並瞭解運算符之間的先後運算順序 在各大常用的電腦語言中都有常見的算術運算符 ...
  • 這篇筆記依然是在做《Python語言程式設計》第5章迴圈的習題。其中有兩類問題需要記錄下來。 第一是如何畫圍棋棋盤。圍棋棋盤共有19縱19橫。其中,位於(0,0)的星位叫天元,其餘8個星位坐標分別是:(-6,6),(0,6),(6,6),(-6,0),(6,0),(-6,-6),(0,-6),(6, ...
  • 稍微關心編程語言的使用趨勢的人都知道,最近幾年,國內最火的兩種語言非 Python 與 Go 莫屬,於是,隔三差五就會有人問:這兩種語言誰更厲害/好找工作/高工資…… 對於編程語言的爭論,就是猿界的生理周期,每個月都要鬧上一回。到了年末,各類榜單也是特別抓人眼球,鬧得更凶。 其實,它們各有對方所無法 ...
  • 一、SSM搭建 1、使用的工具: myeclipse+jdk8+maven+MySQL+Tomcat8.5 2、配製文件截: 二、配置文件 1、web.xml 1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns:xsi="http:// ...
  • 轉載自CSDN的文章 https://blog.csdn.net/gongpulin/article/details/80972806 國內的go get問題的解決 轉載自CSDN的文章 https://blog.csdn.net/gongpulin/article/details/80972806 ...
  • 本文介紹如何自定義迭代器,涉及到類的運算符重載,包括 的索引迭代,以及 、`__next__ __contains__`,如果不瞭解這些知識可跳過本文。 索引迭代方式 索引取值和分片取值 元組、列表、字典、集合、字元串都支持索引取值操作和分片操作。 分片操作實際上將一個slice對象當作索引位傳遞給 ...
  • 1 public static MvcHtmlString PageControl(this HtmlHelper html, PageData page) 2 { 3 if (page == null || page.totalpage == 0) 4 return MvcHtmlString.C... ...
  • class Program { static void Main(string[] args) { Console.WriteLine("please input a number:"); int n =int.Parse ( Console.ReadLine()); int [,] c=new i ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...