Vue3+Vite實現(xiàn)一個Markdown編輯器組件
一、項目背景與需求分析
在現(xiàn)代前端開發(fā)中,Markdown 編輯器廣泛應(yīng)用于博客、文檔、Wiki、代碼注釋等場景。一個優(yōu)秀的 Markdown 編輯器需要具備以下功能:
- 實時預(yù)覽:用戶輸入時,能夠看到實時的渲染效果。
- 語法高亮:支持 Markdown 語法的實時高亮顯示。
- 導(dǎo)出功能:支持將編輯的內(nèi)容導(dǎo)出為 Markdown 或 HTML 格式,方便分享和存檔。
- 自動保存:避免用戶丟失未保存內(nèi)容。
- 文件上傳:支持上傳文件(如圖片),并在 Markdown 內(nèi)容中嵌入顯示。
本文將使用 Vue 3 構(gòu)建一個簡單的 Markdown 編輯器組件,并實現(xiàn)上述基本功能。
二、搭建基礎(chǔ)項目
1. 初始化 Vue 3 項目
我們使用 Vite 來初始化 Vue 3 項目,并選擇 TypeScript 模板:
npm create vite@latest markdown-editor --template vue-ts cd markdown-editor
2. 安裝依賴
接下來,我們安裝實現(xiàn) Markdown 渲染和語法高亮所需要的依賴:
marked:用于將 Markdown 轉(zhuǎn)換為 HTML。
highlight.js:用于提供 Markdown 語法的高亮顯示。
npm install marked highlight.js
三、實現(xiàn) Markdown 編輯器組件
1. 創(chuàng)建 Markdown 編輯器組件
在 src/components 目錄下創(chuàng)建 MarkdownEditor.vue 文件,封裝 Markdown 編輯器功能。
<template> <div class="markdown-editor"> <textarea v-model="content" class="editor-textarea" placeholder="請輸入 Markdown 內(nèi)容..." @input="saveToLocalStorage" ></textarea> <div class="preview"> <div v-html="renderedContent" class="preview-content"></div> </div> <div class="export-buttons"> <button @click="exportMarkdown">導(dǎo)出 Markdown</button> <button @click="exportHTML">導(dǎo)出 HTML</button> </div> <div class="file-upload"> <input type="file" @change="handleFileUpload" /> <p>上傳圖片并在 Markdown 中顯示</p> </div> </div> </template> <script lang="ts"> import { defineComponent, ref, computed, onMounted } from 'vue'; import { marked } from 'marked'; import hljs from 'highlight.js'; export default defineComponent({ name: 'MarkdownEditor', setup() { const content = ref(''); const fileUrl = ref<string | null>(null); // 從本地存儲加載內(nèi)容 onMounted(() => { const savedContent = localStorage.getItem('markdown-content'); if (savedContent) { content.value = savedContent; } }); // 將 Markdown 轉(zhuǎn)換為 HTML 并加上語法高亮 const renderedContent = computed(() => { marked.setOptions({ highlight: (code: string) => { return hljs.highlightAuto(code).value; }, }); return marked(content.value); }); // 保存內(nèi)容到本地存儲(自動保存) const saveToLocalStorage = () => { localStorage.setItem('markdown-content', content.value); }; // 導(dǎo)出 Markdown 內(nèi)容 const exportMarkdown = () => { const blob = new Blob([content.value], { type: 'text/markdown' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = 'document.md'; link.click(); }; // 導(dǎo)出 HTML 內(nèi)容 const exportHTML = () => { const blob = new Blob([renderedContent.value], { type: 'text/html' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = 'document.html'; link.click(); }; // 文件上傳功能 const handleFileUpload = (event: Event) => { const fileInput = event.target as HTMLInputElement; const file = fileInput.files ? fileInput.files[0] : null; if (file) { const reader = new FileReader(); reader.onload = () => { const imageUrl = reader.result as string; fileUrl.value = imageUrl; // 存儲圖片的 URL const markdownImage = ``; // 將圖片路徑轉(zhuǎn)化為 Markdown 格式 content.value += `\n\n${markdownImage}\n`; // 插入到 Markdown 內(nèi)容中 }; reader.readAsDataURL(file); // 將圖片讀取為 Data URL } }; return { content, renderedContent, exportMarkdown, exportHTML, handleFileUpload, }; }, }); </script> <style scoped> .markdown-editor { display: flex; flex-direction: column; gap: 20px; padding: 20px; } .editor-textarea { width: 100%; height: 300px; padding: 10px; font-size: 16px; line-height: 1.5; border: 1px solid #ccc; border-radius: 8px; resize: none; } .preview { background-color: #f8f8f8; padding: 20px; border: 1px solid #ccc; border-radius: 8px; min-height: 300px; } .preview-content { max-width: 100%; word-wrap: break-word; } .export-buttons { display: flex; gap: 10px; } button { padding: 10px 20px; background-color: #007bff; color: white; border: none; border-radius: 8px; cursor: pointer; } button:hover { background-color: #0056b3; } .file-upload { display: flex; flex-direction: column; gap: 10px; } input[type="file"] { padding: 5px; } </style>
2. 組件說明
Markdown 渲染:通過 marked 將用戶輸入的 Markdown 內(nèi)容轉(zhuǎn)換為 HTML。
語法高亮:使用 highlight.js 對代碼塊進(jìn)行高亮顯示,增強(qiáng)代碼閱讀性。
導(dǎo)出功能:支持將 Markdown 或 HTML 內(nèi)容導(dǎo)出為文件,方便用戶保存或分享。
自動保存功能:使用 localStorage 自動保存 Markdown 內(nèi)容,避免用戶丟失未保存的輸入。
文件上傳支持:允許用戶上傳圖片文件,并將圖片插入到 Markdown 內(nèi)容中,生成合適的 Markdown 格式。
四、優(yōu)化與拓展
1. 自動保存功能
通過 localStorage 實現(xiàn)了自動保存功能。每次用戶輸入內(nèi)容時,Markdown 編輯器的內(nèi)容會自動存儲到瀏覽器的本地存儲中。當(dāng)用戶刷新頁面或重新加載時,保存的內(nèi)容會自動恢復(fù)。這樣能有效避免用戶因刷新或瀏覽器崩潰導(dǎo)致的數(shù)據(jù)丟失。
// 保存內(nèi)容到本地存儲(自動保存) const saveToLocalStorage = () => { localStorage.setItem('markdown-content', content.value); };
2. 文件上傳功能
我們通過 HTML5 的 FileReader API 實現(xiàn)了文件上傳支持。當(dāng)用戶上傳圖片文件時,圖片會轉(zhuǎn)換為 Data URL,并自動插入到 Markdown 內(nèi)容中。Markdown 內(nèi)容將以  格式顯示上傳的圖片。
// 文件上傳功能 const handleFileUpload = (event: Event) => { const fileInput = event.target as HTMLInputElement; const file = fileInput.files ? fileInput.files[0] : null; if (file) { const reader = new FileReader(); reader.onload = () => { const imageUrl = reader.result as string; fileUrl.value = imageUrl; // 存儲圖片的 URL const markdownImage = ``; // 將圖片路徑轉(zhuǎn)化為 Markdown 格式 content.value += `\n\n${markdownImage}\n`; // 插入到 Markdown 內(nèi)容中 }; reader.readAsDataURL(file); // 將圖片讀取為 Data URL } };
五、總結(jié)
通過 Vue 3 和 marked、highlight.js,我們實現(xiàn)了一個功能完善的 Markdown 編輯器組件。這個組件不僅支持實時預(yù)覽,還具備了語法高亮與導(dǎo)出功能,極大地方便了用戶的文檔編輯與分享需求。同時,自動保存功能和文件上傳功能進(jìn)一步提升了編輯器的可用性和用戶體驗。
該組件可以輕松地集成到任何 Vue 3 項目中,為你的應(yīng)用增添強(qiáng)大的編輯能力。
到此這篇關(guān)于Vue3+Vite實現(xiàn)一個Markdown編輯器組件的文章就介紹到這了,更多相關(guān)Vue3 Markdown編輯器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue學(xué)習(xí)之Vue-Router用法實例分析
這篇文章主要介紹了vue學(xué)習(xí)之Vue-Router用法,結(jié)合實例形式分析了Vue-Router路由原理與常見操作技巧,需要的朋友可以參考下2020-01-01vue實現(xiàn)的多頁面項目如何優(yōu)化打包的步驟詳解
這篇文章主要介紹了vue實現(xiàn)的多頁面項目如何優(yōu)化打包的步驟詳解,文中通過示例代碼以及圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07