为了账号安全,请及时绑定邮箱和手机立即绑定

ASP.NET Core + Vue 小项目:构造自己的在线 Markdown 笔记本

标签:
Vue.js

目录

  • 概要

  • 知识点

  • 完整示例图

  • 代码与资源文件

  • 流程步骤

概要

基于 MVP 最小可行性产品设计理念,我们先完成一个可以使用,并具备基本功能的 Markdown 笔记本应用,再进行逐步完善。

知识点

本文运用了 Vue 的计算属性、双向绑定、指令、生命周期钩子,还有 localStorage 和异步请求等知识点。

完整示例图

webp

代码与资源文件

https://github.com/liqingwen2015/MarkdownDemo
为了避免网络原因造成的问题,文中所使用的第三方库以及 css 文件都下载好并且已经放入里面。

流程步骤

1.先构建一个基本的 html 文件,并引入核心 js 库。

这里需要引入的第三方库为 vue.js、marked.js。

<html><head>
    <title></title>
    <!-- 引入样式文件 -->
    <link rel="stylesheet" href="index.css" /></head><body>
    <!-- 引入 js 库 -->
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="/lib/vue.js"></script>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="/lib/marked.js"></script>

    <!-- js 代码 -->
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="index.js"></script></body></html>

因为考虑到项目主要划分为两块,左边是书写区域,右边为预览区域,<body> 块代码修改为:

<body>    <!-- 引入 js 库 -->
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="lib/vue.js"></script>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="lib/marked.js"></script>

    <div id="app">
        <!-- 主区域:书写 -->
        <section class="main"></section>

        <!-- 预览区域 -->
        <aside class="preview"></aside>
    </div>

    <!-- js 代码 -->
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="index.js"></script></body>

修改 js 代码:创建 Vue 实例,并将其挂载到 DOM 元素上。

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

【备注】上面的挂载方式是比较常见的一种,我们也可以使用 app.$mount('#app') 进行挂载。

2.接下来我们使用 Vue 的双向绑定机制控制输入的内容和预览的内容。

修改 html:

<body>    <!-- 引入 js 库 -->
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="lib/vue.js"></script>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="lib/marked.js"></script>

    <div id="app">
        <!-- 主区域:书写 -->
        <section class="main">
            <textarea v-model="editor"></textarea>
        </section>

        <!-- 预览区域 -->
        <aside class="preview">
            {{editor}}        </aside>
    </div>

    <!-- js 代码 -->
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="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 class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="lib/vue.js"></script>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="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 class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="index.js"></script></body>

webp

运行效果图

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 class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="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; }
    }



作者:oO反骨仔Oo
链接:https://www.jianshu.com/p/a17033ca91d9


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消