目錄
- 概要
- 知識點
- 完整示例圖
- 代碼與資源文件
- 流程步驟
概要
基于 MVP 最小可行性產(chǎn)品設(shè)計理念缀壤,我們先完成一個可以使用枝嘶,并具備基本功能的 Markdown 筆記本應(yīng)用涩咖,再進行逐步完善。
知識點
本文運用了 Vue 的計算屬性、雙向綁定华望、指令、生命周期鉤子仅乓,還有 localStorage 和異步請求等知識點赖舟。
完整示例圖
代碼與資源文件
https://github.com/liqingwen2015/MarkdownDemo
為了避免網(wǎng)絡(luò)原因造成的問題,文中所使用的第三方庫以及 css 文件都下載好并且已經(jīng)放入里面夸楣。
流程步驟
1.先構(gòu)建一個基本的 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>
因為考慮到項目主要劃分為兩塊,左邊是書寫區(qū)域紧显,右邊為預(yù)覽區(qū)域讲衫,<body> 塊代碼修改為:
<body>
<!-- 引入 js 庫 -->
<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 實例,并將其掛載到 DOM 元素上孵班。
new Vue({
el: '#app'
})
【備注】上面的掛載方式是比較常見的一種涉兽,我們也可以使用 app.$mount('#app') 進行掛載。
2.接下來我們使用 Vue 的雙向綁定機制控制輸入的內(nèi)容和預(yù)覽的內(nèi)容篙程。
修改 html:
<body>
<!-- 引入 js 庫 -->
<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)在,打開 index.html 頁面房午,在瀏覽器頁面中的左側(cè)進行輸入就可以在預(yù)覽窗口中同步看到輸入后的情況矿辽。
3.接下來丹允,我們需要對輸入的內(nèi)容經(jīng)過 Markdown 形式轉(zhuǎn)換郭厌,在這里,我們使用 Vue 的計算屬性來進行優(yōu)化渲染 Markdown 的實時預(yù)覽
修改 js:
new Vue({
// 掛載
el: '#app',
// 數(shù)據(jù)
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">
<!-- 主區(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>
4.保存內(nèi)容
目前扇售,如果關(guān)閉了瀏覽器或者對頁面進行了刷新,所有內(nèi)容都會丟失嚣艇。所以承冰,我們目前使用 localStorage
的方式進行數(shù)據(jù)的保存操作。
現(xiàn)在產(chǎn)生了一個疑問:應(yīng)該什么時候進行保存呢食零?
我們現(xiàn)在使用 Vue 的偵聽器功能來對數(shù)據(jù)的改動進行保存操作困乒,因為它可以監(jiān)聽到 editor 的每一改動操作,意思是每次輸入操作都會觸發(fā)偵聽器里面的方法贰谣。
修改 js:
new Vue({
// 掛載
el: '#app',
// 數(shù)據(jù)
data() {
return {
editor: '編輯器'
}
},
// 計算屬性
computed: {
editorPreview() {
return marked(this.editor);
}
},
// 偵聽器
watch: {
editor(val) {
localStorage.setItem('editor', this.editor);
}
}
})
那么現(xiàn)在又產(chǎn)生了新的疑問:應(yīng)該怎樣才能夠在每次進入這個頁面時顯示之前保存的信息呢娜搂?
現(xiàn)在迁霎,我們通過利用 Vue 的生命周期鉤子(目前使用 created 鉤子)來進行數(shù)據(jù)的讀取及恢復(fù)。
修改 js:
new Vue({
// 掛載
el: '#app',
// 數(shù)據(jù)
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考廉,這會導(dǎo)致整個應(yīng)用出錯,所以這里采用了默認值携御。
5.localStorage 畢竟不是永久保存的方式昌粤,這里我使用一種較為簡單的方式,保存方法替換為異步請求到 WebApi 接口保存到數(shù)據(jù)庫的方式
修改 html啄刹,引入 axios 庫:
<script src="lib/axios.min.js"></script>
同時婚苹,修改 js,增加兩個 Http 請求的方法鸵膏,獲取和保存:
new Vue({
// 掛載
el: '#app',
// 數(shù)據(jù)
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 的內(nèi)容如下:
[Route("api/[controller]")]
[ApiController]
public class MarkdownController : ControllerBase
{
public static MarkdownViewModel MarkdownViewModel = new MarkdownViewModel()
{
Content = "我的第一個 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; }
}
【備注】需要自行進行 WebApi 的跨域配置膊升,演示時進行了忽略配置
【備注】示例代碼可從 https://github.com/liqingwen2015/MarkdownDemo 下載
【切換閱讀方式】https://www.cnblogs.com/liqingwen/p/10264626.html
【參考】Vue.js 2 Web Development Projects