iT邦幫忙

2023 iThome 鐵人賽

DAY 15
0
Vue.js

業主說給你30天學會Vue系列 第 15

V15_從Vue的範例做中學(1)_Markdown_Editor

  • 分享至 

  • xImage
  •  

V15_從Vue的範例做中學(1)_Markdown_Editor

前面幾篇的發文已經大致的了解Vue的主要的特性及用法了,
接下來要轉到Vue的官網上的Example範例,
透過範例,來學習及驗證Vue的功能是否都有理解了,或是還有待確認的地方
經過幾篇的範例學習之後,就可以來挑戰一個小專案的規模了

首先,從 Markdown Editor 開始
來學習建立一個最簡單的 Markdown編輯器

網址如下
https://vuejs.org/examples/#markdown
這個範例只有一個App.vue

<!--
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
}, 10000)
</script>

<template>
  <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>

Markdown 是一套可以在純文字編輯下透過特別符號符標記,
就可以轉換或是渲染成具有樣式的網頁內容

像是 # hello 就會渲染成 <h1>hello</h1>

[iT邦幫忙](https://ithelp.ithome.com.tw)

就會渲染成

<a href="https://ithelp.ithome.com.tw">iT邦幫忙</a>
**粗體** 就會渲染成 <strong>粗體</strong>
*斜體* 就會渲染成 <em>斜體</em>

https://ithelp.ithome.com.tw/upload/images/20230929/20152098arvZ8H8W8o.png

詳細語法可以參考 Markdown說明 的網頁介紹
https://ithelp.ithome.com.tw/markdown

接著來看一下程式

先從<template>看起

<template>
  <div class="editor">
    <textarea class="input" :value="input" @input="update"></textarea>
    <div class="output" v-html="output"></div>
  </div>
</template>

<template>中,有一個<textarea>作為輸入原始純文字 Markdown 的區域,<div>則是渲染成網頁內容的區塊。
<textarea class="input">中,宣告input變數綁定了value值 :value, 用function update綁定input事件@input,

<div class="output">中,用output設定v-html,

<script setup>的部份

<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
}, 10000)
</script>

<script setup>

import { marked } from 'marked'
import { debounce } from 'lodash-es'

這2個套件屬於要另外匯入,所以需要另外編輯 這些檔案 'tsconfig.json' 'Import Map'
也就是要有一個安裝的動作,以及套件路徑的設定,這樣程式才讀得到 'marked''lodash-es'

這部份屬於如何整合,加入外掛套件的部份,
會另外一篇發文來介紹

在此因為是利用官網上的線上編輯器,已經都是安裝好套件的狀態了。

input 是ref物件,初值是 '# hello' 會動態回應到 :value

output 是宣告接受 computed()回傳的內容,這個內容是 將input.value經過marked()變成網頁格式內容
marked() 是從 'marked' 套件匯入的 marked的功能
就是 import { marked } from 'marked'

另外 @input 事件,是在輸入文字內容時,觸發 function update,
update 會執行

debounce((e) => {
  input.value = e.target.value
}, 1000)

其中看到debounce()的功能,這是一個類似延後執行的意思,為了畢免太過頻繁的觸發update,
使用debounce( (e)=>{}, 1000) 就是輸入後間隔1000ms(毫秒),才對有觸發input的事件執行動作,
有點像是,在輸入的同時不會一直update, 而是輸入後1秒才會update,是一個針對輸入文字時,很有用的功能,
而這個 debounce()的功能,也是要經過'lodash-es'套件匯入
就是

import { debounce } from 'lodash-es' 

再來就是 e.target.value 指的是 觸發的事件e, e.target是<textarea>的事件對象,
e.target.value 是<textarea>的value值,再傳給input.value,input再連動到 <textarea :value="input"> 這看起來像是自己輸入完1秒後更新<textarea>的value內容

最後,再透過 const output = computed(() => marked(input.value))input.value一變動,就立即更新到 <div class="output" v-html="output">的內容
其中 v-html 參考vue.js官網的說明
https://vuejs.org/api/built-in-directives.html#v-html

是指對於綁定的內容,會照原始的內容格式呈現,就是 marked(input.value)的結果是html的格式,加上v-html綁定,就是<div>的內容會以html的內容呈現,而不是當作純文字呈現,
因為會當作是html的內容呈現,如果輸入的是一些惡意的程式碼的話,就會被執行,造成資安的問題,
所以除非是在很信任的條件下,才能安全的使用v-html

在這個狀態下

<div class="output" v-html="output"></div>

像是如果輸入如下

# hello

<b>ABC</b>

<div onclick="alert('OK');"> AAA </div>

<a href="http://www.processing.org">processing</a>
<div class="output" v-html="output"></div>
<div class="output" v-html="output"></div>
# hello -> 會以h1標題呈現

<b>ABC</b> -> 會以粗體呈現 

<div onclick="alert('OK');"> AAA </div>  -> click時 會觸發執行alert('OK');

<a href="http://www.processing.org">processing</a> -> 會以超連結呈現,點下後可連到新網頁

https://ithelp.ithome.com.tw/upload/images/20230929/20152098jx2WdF6KPj.png

若改成

<div class="output">{{ output }}</div> 

的話

同樣的輸入
會變成有html格式純文字呈現了

<h1>hello</h1> <p><b>ABC</b></p> <div onclick="alert('OK');"> AAA </div> <p><a href="http://www.processing.org">processing</a></p>

https://ithelp.ithome.com.tw/upload/images/20230929/20152098At0M7wcswR.png

<style> 的部份

.editor {
  height: 100vh;
  display: flex;
}

.input,
.output {
  overflow: auto;
  width: 50%;
  height: 100%;
  box-sizing: border-box;
  padding: 0 20px;
}

會產生

<textarea class="input" :value="input" @input="update"></textarea>
<div class="output" v-html="output"></div>

左右並排的結果

https://ithelp.ithome.com.tw/upload/images/20230929/20152098Zxni3riuDZ.png

若改成

.editor {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.input,
.output {
  overflow: auto;
  width: 100%;
  height: 50%;
  box-sizing: border-box;
  padding: 0 20px;
}

就會變成上下排列的結果

https://ithelp.ithome.com.tw/upload/images/20230929/20152098ExZjS9axoJ.png

從這個範例可以嘗試找出要導入Vue的框架時,
思考的順序,綁定,連動,事件的連鎖關係,

像是先從基本的<template>內容開始,
接著是各種的 綁定,連動,事件 的設定,
然後是在<script>中,宣告對應的變數,ref物件,還有function的設定
最後是<style>樣式的設定及綁定連動設定

後面的幾篇發文,可以藉此看看有什麼新的應用


上一篇
V14_快速檢視Vue的功能(4)_Vue元件之間的props、emits與slots
下一篇
V16_從Vue的範例做中學(2)_Fetching_Data
系列文
業主說給你30天學會Vue31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言