Vue組件開發 -- Markdown

利用marked 和 highlight.js開發markdown組件html

實現效果圖以下:vue

938b4748d2e28.gif

markdown組件已這種形式<Markdown v-model="markdown"></Markdown>來綁定markdown的值
咱們能夠經過 value prop 和 input事件來達到這個效果用法詳情ios

代碼部分:git

<Markdown v-model="markdown"></Markdown>

markdown組件

1.響應v-modelgithub

// 經過監聽input事件 觸發handleModelInput方法
<textarea v-model="val" @input="handleModelInput" ref="text" @keydown.tab="tabMarkdown"></textarea>

import marked from 'marked'
import highlightJs from 'highlight.js'
export default {
    props: ['value'],
    data() {
        return {
            val: this.value
        }
    },
    methods: {
        handleModelInput() {// 經過$emit來把值返回給父組件
            this.$emit('input', this.val)
        }
    }
}

2.插入markdown語法axios

async insertImg(e) { // 插入圖片
    let formData = new FormData(),
        img = '';
    formData.append('img', e.target.files[0]);
    try {
        let data = await this.axios({
            method: 'post',
            url: 'http://localhost:3000/markdown_upload_img',
            data: formData
        })
        img = data.data.img
    } catch (e) {
        console.log(e)
    }
    
    let val = `![圖片描述](${img})`
    this.setCursorPosition(this.$refs.text, val, 6)
},
insertLink () { //插入連接
    this.maskBol = false
    let val = `[連接描述](${this.link})`
    this.setCursorPosition(this.$refs.text, val, 5)
},
setCursorPosition (dom,val,posLen) { // 設置光標位置
    var cursorPosition = 0;
    if(dom.selectionStart){
        cursorPosition = dom.selectionStart;
    }
    this.insertAtCursor(dom,val);
    dom.focus();
    dom.setSelectionRange(dom.value.length,cursorPosition + (posLen || val.length));
    this.val = dom.value
},
insertAtCursor(dom, val) { // 光標所在位置插入字符
    if (document.selection){
        dom.focus();
        sel = document.selection.createRange();
        sel.text = val;
        sel.select();
    }else if (dom.selectionStart || dom.selectionStart == '0'){
        let startPos = dom.selectionStart;
        let endPos = dom.selectionEnd;
        let restoreTop = dom.scrollTop;
        dom.value = dom.value.substring(0, startPos) + val + dom.value.substring(endPos, dom.value.length);
        if (restoreTop > 0){
            dom.scrollTop = restoreTop;
        }
        dom.focus();
        dom.selectionStart = startPos + val.length;
        dom.selectionEnd = startPos + val.length;
    } else {
        dom.value += val;
        dom.focus();
    }
}

經過 setCursorPositioninsertAtCursor方法 插入光標所在位置並設置光標位置segmentfault

  1. 轉化markdown語法顯示區域
<div class="render fmt" v-html="renderHtml"></div>

// 實時轉化textarea裏面的markdown語法
computed: {
    renderHtml() {
        marked.setOptions({
            renderer: new marked.Renderer(),
            gfm: true, //容許 Git Hub標準的markdown.
            tables: true, //容許支持表格語法。該選項要求 gfm 爲true。
            breaks: true, //容許回車換行。該選項要求 gfm 爲true。
            pedantic: false, //儘量地兼容 markdown.pl的晦澀部分。不糾正原始模型任何的不良行爲和錯誤。
            sanitize: true, //對輸出進行過濾(清理),將忽略任何已經輸入的html代碼(標籤)
            smartLists: true, //使用比原生markdown更時髦的列表。 舊的列表將可能被做爲pedantic的處理內容過濾掉.
            smartypants: false, //使用更爲時髦的標點,好比在引用語法中加入破折號。
            highlight: function (code) {
                return highlightJs.highlightAuto(code).value;
            }
        });
        return marked(this.val)
    }
}

由於習慣使用tab縮進,因此在textarea裏面輸入的時候 按tab會切換元素,不會進行縮進, 全部咱們得處理下tab鍵markdown

tabMarkdown (e) { // 禁止tabs鍵的默認事件,並設置tab等於4個空格
    e.preventDefault()
    let indent = '    '
    let start = this.textarea.selectionStart
    let end = this.textarea.selectionEnd
    let selected = window.getSelection().toString()
    selected = indent + selected.replace(/\n/g, '\n' + indent)
    this.textarea.value = this.textarea.value.substring(0, start) + selected
            + this.textarea.value.substring(end);
    this.textarea.setSelectionRange(start + indent.length, start
            + selected.length)
}

markdown樣式我是直接從 segmentfault上摳下來的app

完整代碼,點此獲取

博客地址dom

相關文章
相關標籤/搜索