ASP.NET Core + Vue 小項(xiàng)目:構(gòu)造自己的在線 Markdown 筆記本

目錄

  • 概要
  • 知識(shí)點(diǎn)
  • 完整示例圖
  • 代碼與資源文件
  • 流程步驟

概要

基于 MVP 最小可行性產(chǎn)品設(shè)計(jì)理念,我們先完成一個(gè)可以使用,并具備基本功能的 Markdown 筆記本應(yīng)用,再進(jìn)行逐步完善。

知識(shí)點(diǎn)

本文運(yùn)用了 Vue 的計(jì)算屬性、雙向綁定、指令、生命周期鉤子,還有 localStorage 和異步請(qǐng)求等知識(shí)點(diǎn)。

完整示例圖

代碼與資源文件

https://github.com/liqingwen2015/MarkdownDemo
為了避免網(wǎng)絡(luò)原因造成的問(wèn)題,文中所使用的第三方庫(kù)以及 css 文件都下載好并且已經(jīng)放入里面。

流程步驟

1.先構(gòu)建一個(gè)基本的 html 文件,并引入核心 js 庫(kù)。

這里需要引入的第三方庫(kù)為 vue.js、marked.js。

<html>

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

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

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

</html>

因?yàn)榭紤]到項(xiàng)目主要?jiǎng)澐譃閮蓧K,左邊是書寫區(qū)域,右邊為預(yù)覽區(qū)域,<body> 塊代碼修改為:

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

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

        <!-- 預(yù)覽區(qū)域 -->
        <aside class="preview"></aside>
    </div>

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

修改 js 代碼:創(chuàng)建 Vue 實(shí)例,并將其掛載到 DOM 元素上。

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

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

2.接下來(lái)我們使用 Vue 的雙向綁定機(jī)制控制輸入的內(nèi)容和預(yù)覽的內(nèi)容。

修改 html:

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

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

        <!-- 預(yù)覽區(qū)域 -->
        <aside class="preview">
            {{editor}}
        </aside>
    </div>

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

修改 js,增加數(shù)據(jù)屬性:

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

現(xiàn)在,打開(kāi) index.html 頁(yè)面,在瀏覽器頁(yè)面中的左側(cè)進(jìn)行輸入就可以在預(yù)覽窗口中同步看到輸入后的情況。

3.接下來(lái),我們需要對(duì)輸入的內(nèi)容經(jīng)過(guò) Markdown 形式轉(zhuǎn)換,在這里,我們使用 Vue 的計(jì)算屬性來(lái)進(jìn)行優(yōu)化渲染 Markdown 的實(shí)時(shí)預(yù)覽

修改 js:

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

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

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

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

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

        <!-- 預(yù)覽區(qū)域 -->
        <aside class="preview" v-html="editorPreview"> </aside>
    </div>

    <!-- js 代碼 -->
    <script src="index.js"></script>
</body>
運(yùn)行效果圖

4.保存內(nèi)容

目前,如果關(guān)閉了瀏覽器或者對(duì)頁(yè)面進(jìn)行了刷新,所有內(nèi)容都會(huì)丟失。所以,我們目前使用 localStorage
的方式進(jìn)行數(shù)據(jù)的保存操作。

現(xiàn)在產(chǎn)生了一個(gè)疑問(wèn):應(yīng)該什么時(shí)候進(jìn)行保存呢?

我們現(xiàn)在使用 Vue 的偵聽(tīng)器功能來(lái)對(duì)數(shù)據(jù)的改動(dòng)進(jìn)行保存操作,因?yàn)樗梢员O(jiān)聽(tīng)到 editor 的每一改動(dòng)操作,意思是每次輸入操作都會(huì)觸發(fā)偵聽(tīng)器里面的方法。

修改 js:

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

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

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

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

那么現(xiàn)在又產(chǎn)生了新的疑問(wèn):應(yīng)該怎樣才能夠在每次進(jìn)入這個(gè)頁(yè)面時(shí)顯示之前保存的信息呢?

現(xiàn)在,我們通過(guò)利用 Vue 的生命周期鉤子(目前使用 created 鉤子)來(lái)進(jìn)行數(shù)據(jù)的讀取及恢復(fù)。

修改 js:

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

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

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

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

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

【備注】在進(jìn)行修改 js 后,editor 屬性第一次加載的時(shí)候可能為 null,這會(huì)導(dǎo)致整個(gè)應(yīng)用出錯(cuò),所以這里采用了默認(rèn)值。

5.localStorage 畢竟不是永久保存的方式,這里我使用一種較為簡(jiǎn)單的方式,保存方法替換為異步請(qǐng)求到 WebApi 接口保存到數(shù)據(jù)庫(kù)的方式

修改 html,引入 axios 庫(kù):

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

同時(shí),修改 js,增加兩個(gè) Http 請(qǐng)求的方法,獲取和保存:

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

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

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

    // 偵聽(tīng)器
    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 的內(nèi)容如下:

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

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

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

視圖模型 MarkdownViewModel.cs 的內(nèi)容如下:

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

【備注】需要自行進(jìn)行 WebApi 的跨域配置,演示時(shí)進(jìn)行了忽略配置
【備注】示例代碼可從 https://github.com/liqingwen2015/MarkdownDemo 下載

【切換閱讀方式】https://www.cnblogs.com/liqingwen/p/10264626.html
【參考】Vue.js 2 Web Development Projects

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 33、JS中的本地存儲(chǔ) 把一些信息存儲(chǔ)在當(dāng)前瀏覽器指定域下的某一個(gè)地方(存儲(chǔ)到物理硬盤中)1、不能跨瀏覽器傳輸:在...
    萌妹撒閱讀 2,098評(píng)論 0 2
  • vue-cli搭建項(xiàng)目 確保安裝了node與npm 再目標(biāo)文件夾下打開(kāi)終端 執(zhí)行cnpm i vue-cli -g...
    Akiko_秋子閱讀 3,273評(píng)論 1 22
  • 在尤大微博鋪墊著“將會(huì)引入一些關(guān)于 TypeScript 的改進(jìn)”一周之后,代號(hào)為 Level E 的 Vue.j...
    極樂(lè)叔閱讀 14,869評(píng)論 0 12
  • ## 框架和庫(kù)的區(qū)別?> 框架(framework):一套完整的軟件設(shè)計(jì)架構(gòu)和**解決方案**。> > 庫(kù)(lib...
    Rui_bdad閱讀 2,961評(píng)論 1 4
  • 活著,僅僅是活著。你夢(mèng)想的樣子可能與你實(shí)際的處境相差十萬(wàn)八千里,只是你心安而已,覺(jué)得這樣的生活有意義,這樣活...
    7d3dec75a0f5閱讀 393評(píng)論 0 1