Vue + WebApi 小项目:构造自己的在线 Markdown 笔记本应用

时间:2022-11-04 18:42:14

Vue + WebApi 小项目:构造自己的在线 Markdown 笔记本应用

目录

  • 概要
  • 知识点
  • 完整示例图
  • 代码与资源文件
  • 流程步骤

概要

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

知识点

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

完整示例图

 
Vue + WebApi 小项目:构造自己的在线 Markdown 笔记本应用
 

代码与资源文件

  https://github.com/liqingwen2015/MarkdownDemo

  为了避免网络原因造成的问题,文中所使用的第三方库(可自己去官方下载最新版,文章使用的是当前发布时间最新版本的 js 文件)以及 css 文件都下载好并且已经放入里面。

body {
font-family: sans-serif;
font-size: 16px;
height: 100%;
margin:;
box-sizing: border-box;
} .material-icons {
font-size: 24px;
line-height:;
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:;
} 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>
 
Vue + WebApi 小项目:构造自己的在线 Markdown 笔记本应用
运行效果图

  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

Vue + WebApi 小项目:构造自己的在线 Markdown 笔记本应用的更多相关文章

  1. 跟我一起做一个vue的小项目(二)

    这个vue项目是紧跟着之前的项目跟我一起做一个vue的小项目(一)来的. 我继续后面的开发(写的比较粗糙,边学边记录) 下图是header头部的样式 header组件内容如下 //header.vue ...

  2. 跟我一起做一个vue的小项目(APPvue2&period;5完结篇)

    先放一下这个完结项目的整体效果 下面跟我我一起进行下面项目的进行吧~~~ 接下来我们进行的是实现header的渐隐渐显效果,并且点击返回要回到首页 我们先看效果 在处理详情页向下移动过程中,heade ...

  3. 跟我一起做一个vue的小项目(八)

    接下来我们进行的是城市选择页面的路由配置 添加city.vue,使其点击城市,然后跳转到city页面 //router.js import Vue from 'vue' import Router f ...

  4. 跟我一起做一个vue的小项目(七)

    先看下我们所做项目的效果 这些数据都是我们在data中定义的,不是从后端数据中请求的.那么 接下来我们使用axios渲染数据 npm install axios --save 每个组件里面的数据都不相 ...

  5. 跟我一起做一个vue的小项目(五)

    接下来我们要做的是热门推荐页面,我们写一个推荐组件 使用的方法也是前端data中的数据渲染到页面上面,这里对文字过长取省略号的方法不成功使用了一个小技巧 使用了min-width:0 我们来看完整的代 ...

  6. 跟我一起做一个vue的小项目(四)

    接下来我们进行的是轮播页面下面的导航页的开发 我们需要的是实现轮播页下面的图标,并且实现轮播效果 这个话,其实基本思路先是渲染出小图标,然后,我们要对页数进行判断,如果图标的个数展示的就是8个,那个这 ...

  7. 跟我一起做一个vue的小项目(三)

    接下来我们进行轮播的开发 安装插件,选用2.6.7的稳定版本 npm install vue-awesome-swiper@2.6.7 --save 根据其github上面的用法,我们在全局引用,在m ...

  8. 跟我一起做一个vue的小项目&lpar;一&rpar;

    项目架子 npm install --global vue-cli vue init webpack travel cd travel/ npm run dev 运行效果 添加home页及其路由,添加 ...

  9. 跟我一起做一个vue的小项目(十一)

    接下来我们进行的是详情页动态路由及banner布局 先看页面的效果 下面是代码部分 <template> <div> <div class="banner&qu ...

随机推荐

  1. JS刷新父窗口的几种方式&lt&semi;转&gt&semi;

    常用的有:   window.opener.location.reload();    和  window.location.reload(); 浮层内嵌iframe及frame集合窗口,刷新父页面的 ...

  2. session和request的区别

    request 请求对象 请求中保存请求过程中需要的参数 比如另一个页面需要使用的对象编号,list,map等,请求结束,就失效了 session 会话对象 除非关闭会话(到时间通常为30分钟,或者关 ...

  3. hdu Counting Sheepsuanga

    算法:深搜 题意:让你判断一共有几个羊圈: 思路:像四个方向搜索: Problem Description A while ago I had trouble sleeping. I used to ...

  4. 发送cookie

  5. eclipse修改java代码后报错: java&period;lang&period;OutOfMemoryError&colon; PermGen space

    由于在eclipse中运行项目后,我们又重新修改了某个java类,导致tomcat会重新加载这个项目所有的class.jar,多次加载后由于分配的存储空间有限,就导致了:java.lang.OutOf ...

  6. 年度酷工作---高级数据工程师(公司靠谱,技术强悍,产品牛叉,福利有干货) 关键词:7000万用户、五星级厨师、住房补助 - V2EX

    年度酷工作---高级数据工程师(公司靠谱,技术强悍,产品牛叉,福利有干货) 关键词:7000万用户.五星级厨师.住房补助 - V2EX 年度酷工作---高级数据工程师(公司靠谱,技术强悍,产品牛叉,福 ...

  7. 使用Docker搭建Jenkins&plus;Docker持续集成环境(自动化构建发布部署)

    本文介绍如何通过Jenkins的docker镜像从零开始构建一个基于docker镜像的持续集成环境,包含自动化构建.发布到仓库\并部署上线. 0. 前置条件 服务器安装docker,并启动docker ...

  8. Spring源码情操陶冶-自定义节点的解析

    本文承接前文Spring源码情操陶冶-DefaultBeanDefinitionDocumentReader#parseBeanDefinitions,特开辟出一块新地来啃啃这块有意思的骨头 自定义节 ...

  9. 关于访问Jira和Confluence服务越来越缓慢的解决办法阐述

    Jira和Confluence部署在同一台服务器上,跑一段时间后,发现访问jira和confluence时,打开越来越缓慢.这是因为根据主机物理内存不同,默认的java虚拟机内存也会不同(一个较低值) ...

  10. Vue可复用过渡和动态过渡

    前面的话 本文将详细介绍Vue可复用过渡和动态过渡 可复用过渡 过渡可以通过 Vue 的组件系统实现复用.要创建一个可复用过渡组件,需要做的就是将 <transition> 或者 < ...