看官方文件看個幾篇就好累~
終於輪到實用範例摟!
這篇要做一個Markdown編輯器,真的假的?!?
首先在開啟第二組實用練習之前,我要把先前的範例整理到一個View裡頭,先前的邏輯是 index.html ⮕ main.js ⮕ App.vue 再把畫面渲染到id=App的元素上,現在要將資料夾內容改成以下的狀況,目的是要把一些練習組件放在Views裡頭管理
研究一下可以用vue router來控管一下view頁面,先來去npm安裝一下。
安裝指令:
npm install vue-router@4
安裝完之後,要進行入口修改一下
創建Router資料夾,並建立index.js
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router';
// createApp(App).mount('#app')
createApp(App).use(router).mount('#app');
import { createRouter, createWebHistory } from 'vue-router';
import BasicExamples from '../views/BasicExamples.vue';
import PracticalExamples from '../views/PracticalExamples.vue';
const routes = [
{ path: '/basic-examples', component: BasicExamples },
{ path: '/practical-examples', component: PracticalExamples },
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
<script setup>
import { RouterView } from 'vue-router';
</script>
<template>
<div class="app-container">
<div class="nav-container">
<div class="card">
<router-link to="/basic-examples">Basic Examples</router-link>
</div>
<div class="card">
<router-link to="/practical-examples">Practical Examples</router-link>
</div>
</div>
<div class="content-container">
<RouterView />
</div>
</div>
</template>
<style>
.app-container {
display: flex;
/* 使用 Flexbox 排版 */
width: 100%;
}
.nav-container {
display: flex;
flex-direction: column;
/* 使導航項目垂直排列 */
margin: 2rem 0;
gap: 1rem;
/* 設定導航欄的寬度 */
width: 200px;
/* 導航欄固定寬度 */
}
.card {
background: white;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
padding: 2rem;
text-align: center;
transition: transform 0.2s;
}
.card:hover {
transform: scale(1.05);
}
.card a {
color: #42b983;
text-decoration: none;
font-size: 1.2rem;
font-weight: bold;
}
.card a:hover {
text-decoration: underline;
}
.content-container {
/* max-width: 1200px; */
/* 最大寬度 */
width: 100%;
/* 寬度100% */
margin: 0 auto;
/* 自動左右邊距使其居中 */
padding: 20px;
/* 內邊距 */
}
@media (min-width: 1024px) {
#app {
display: block;
/* 使用 block 或其他佈局 */
/* 移除 grid-template-columns */
padding: 0 2rem;
/* 保留內邊距 */
}
}
</style>
有了router之後,邏輯變成這樣
index.html ⮕ main.js ⮕ App.vue + index.js
Vue Router 是 Vue.js 的官方路由管理器,用於構建單頁應用程序 (SPA)。它的主要功能是根據當前的 URL 路徑來顯示不同的視圖組件。以下是 Vue Router 的運作過程和效果的簡要說明:
index.html
中的 div
元素設置了 id="app"
。這個 div
是 Vue 應用的根容器。main.js
中,創建了 Vue 應用實例,並將它掛載到 #app
元素上。同時,Vue Router 被引入並使用。App.vue
作為根組件,其中包含了導航欄和 RouterView
。RouterView
是一個占位組件,會根據當前路由顯示相應的視圖。router/index.js
中定義了路由配置,這些配置決定了 URL 對應哪個組件。<router-link>
元素創建的導航鏈接,可以在應用內部切換不同的路徑,從而改變 RouterView
中顯示的內容。為了確保內容區域在寬螢幕下顯示正常,移除不必要的樣式,並確保 #app
沒有多餘的樣式影響:
@media (min-width: 1024px) {
#app {
display: block; /* 使用 block 或其他佈局 */
/* 移除 grid-template-columns */
padding: 0 2rem; /* 保留內邊距 */
}
}
// 範例 安裝套件
npm install marked
npm install lodash-es
<!--
A simple markdown editor.
-->
<script setup>
import { marked } from 'marked'
import { debounce } from 'lodash-es'
import { ref, computed } from 'vue'
const input = ref('# hello')
const output = computed(() => marked(input.value))
const update = debounce((e) => {
input.value = e.target.value
}, 100)
</script>
<template>
<p>Example 1:</p>
<div class="editor">
<textarea class="input" :value="input" @input="update"></textarea>
<div class="output" v-html="output"></div>
</div>
</template>
<style>
body {
margin: 0;
}
.editor {
height: 100vh;
display: flex;
}
.input,
.output {
overflow: auto;
width: 50%;
height: 100%;
box-sizing: border-box;
padding: 0 20px;
}
.input {
border: none;
border-right: 1px solid #ccc;
resize: none;
outline: none;
background-color: #f6f6f6;
font-size: 14px;
font-family: 'Monaco', courier, monospace;
padding: 20px;
}
code {
color: #f66;
}
</style>
<script setup>
部分引入模組
<script setup>
import { marked } from 'marked' // 引入 marked 庫,用於將 Markdown 轉換為 HTML
import { debounce } from 'lodash-es' // 引入 lodash-es 的 debounce 函數,用於防止頻繁觸發輸入事件
import { ref, computed } from 'vue' // 從 Vue 中引入 ref 和 computed 函數
定義狀態和計算屬性
const input = ref('# hello') // 定義一個 ref 變數 input,初始值為 '# hello'
const output = computed(() => marked(input.value)) // 定義一個 computed 屬性 output,值為將 input 的值轉換為 HTML 後的結果
定義更新函數
const update = debounce((e) => {
input.value = e.target.value // 定義一個 update 函數,使用 debounce 來限制頻繁觸發。當輸入框內容變化時,更新 input 的值
}, 100) // debounce 時間設置為 100 毫秒
</script>
<template>
部分<template>
<p>Example 1:</p> <!-- 顯示一個標題 "Example 1:" -->
<div class="editor">
<textarea class="input" :value="input" @input="update"></textarea> <!-- 輸入框,綁定 input 變數,當輸入變化時觸發 update 函數 -->
<div class="output" v-html="output"></div> <!-- 輸出區域,顯示由 output 計算屬性生成的 HTML -->
</div>
</template>
<style>
部分body {
margin: 0; // 設置 body 元素的 margin 為 0,去除預設的外邊距
}
.editor {
height: 100vh; // 設置編輯器的高度為視窗高度的 100%
display: flex; // 使用 flexbox 排版
}
.input,
.output {
overflow: auto; // 設置溢出時顯示滾動條
width: 50%; // 設置輸入和輸出區域的寬度各占 50%
height: 100%; // 設置高度為 100%
box-sizing: border-box; // 設置 box-sizing 為 border-box,包含 padding 和 border 在內的總寬度和高度
padding: 0 20px; // 設置左右 padding 為 20px
}
.input {
border: none; // 移除邊框
border-right: 1px solid #ccc; // 設置右邊框為 1px 寬的實線,顏色為 #ccc
resize: none; // 禁止調整大小
outline: none; // 移除聚焦時的外輪廓
background-color: #f6f6f6; // 設置背景顏色為 #f6f6f6
font-size: 14px; // 設置字體大小為 14px
font-family: 'Monaco', courier, monospace; // 設置字體為 Monaco, courier, monospace
padding: 20px; // 設置內邊距為 20px
}
code {
color: #f66; // 設置 code 元素的字體顏色為 #f66
}
</style>
這個 Markdown 編輯器主要分為三個部分:
<textarea>
元素來輸入 Markdown 內容,並綁定到 Vue 的 input
變數。<div>
元素來顯示轉換後的 HTML 內容,並綁定到 Vue 的 output
計算屬性。透過 marked
將 Markdown 轉換為 HTML,並使用 lodash-es
的 debounce
函數來防止頻繁觸發輸入事件,這樣可以避免性能問題。
經由import了兩個套件,以及短短的60行就實現了一個簡易的Markdown編輯器,
真的蠻有趣的!!!藉此也了解到debounce函數的用法~
然後慢慢地把範例檔案集中在這裡~Readme等有空再整理~ vue example
以下是測試Markdown的效果,大家快來玩看看吧~