天天看點

基于uniapp+vue3渲染markdown文法|軟鍵盤頂起問題

作者:web前端進階

#夏日生活打卡季#

今天來給大家分享最新基于uni-app vite4搭建vue3跨端項目,渲染markdown/html解析,鍵盤被撐起問題。

基于uniapp+vue3渲染markdown文法|軟鍵盤頂起問題

經過一番調試,目前支援h5/小程式/APP端 markdown解析,鍵盤撐起擠壓問題。

基于uniapp+vue3渲染markdown文法|軟鍵盤頂起問題

uni-app渲染markdown及文法高亮

uniapp vue3中渲染markdown文法及代碼高亮,在應用市場也有一些插件,不過相容性不是很好,要麼隻支援h5或小程式。

給大家介紹一種方法,使用markdown-it和highlight.js插件。

import MarkdownIt from '@/plugins/markdown-it.min.js'
import hljs from '@/plugins/highlight/highlight.min.js'
// import '@/plugins/highlight/github-dark.min.css'
import '@/plugins/highlight/atom-one-light.css'
import parseHtml from '@/plugins/html-parser.js'           

初始化插件

const markdown = MarkdownIt({
	 html: true,
	 highlight: function(str, lang) {
		let preCode = ""
		try {
			preCode = hljs.highlightAuto(str).value
		} catch (err) {
			preCode = markdown.utils.escapeHtml(str);
		}
		// 自定義行号
		const lines = preCode.split(/\n/).slice(0, -1)
		let html = lines.map((item, index) => {
			// 去掉空行
			if( item == ''){
				return ''
			}
			return '<li><span class="line-num" data-line="' + (index + 1) + '"></span>' + item +'</li>'
		}).join('')
		html = '<ol style="padding: 0px 30px;">' + html + '</ol>'
		
		// 代碼複制
		copyCode.push(str)
		let htmlCode = `<div class="markdown-wrap">`
			// #ifndef MP-WEIXIN
				htmlCode += `<div style="color: #aaa;text-align: right;font-size: 12px;padding:8px;">`
					htmlCode += `${lang}<a class="copy-btn" code-data-index="${copyCode.length - 1}" style="margin-left: 8px;">複制代碼</a>`
				htmlCode += `</div>`
			// #endif
				htmlCode += `<pre class="hljs" style="padding:0 8px;margin-bottom:5px;overflow: auto;display: block;border-radius: 5px;"><code>${html}</code></pre>`;
			htmlCode += '</div>'
		return htmlCode
	}
})           

解析markdown文法

const parseNodes = (value) => {
	 if(!value) return
	 
	 let htmlString = ''
	if (value.split("```").length % 2) {
		let msgContent = value
		if(msgContent[msgContent.length-1] != '\n'){
			msgContent += '\n'
		}
		htmlString = markdown.render(msgContent)
	} else {
		htmlString = markdown.render(msgContent.value)
	}
	
	// #ifndef APP-NVUE
	return htmlString
	// #endif
	
	// nvue模式下将htmlString轉成htmlArray,其他情況rich-text内部轉
	// 注:本示例項目還沒使用nvue編譯
	// #ifdef APP-NVUE
	return parseHtml(htmlString)
	// #endif
}           
基于uniapp+vue3渲染markdown文法|軟鍵盤頂起問題

使用rich-text元件調用解析後的内容。

<rich-text space="nbsp" :nodes="parseNodes(item.content)" @itemclick="handleItemClick"></rich-text>           

使用rich-text元件的itemclick方法實作複制代碼功能。

// 複制代碼
const handleItemClick = (e) => {
	console.log(e);
	let {attrs} = e.detail.node
	console.log({attrs});
	let {"code-data-index": codeDataIndex, "class": className} = attrs
	if(className == 'copy-btn'){
		uni.setClipboardData({
			data:copyCode[codeDataIndex],
			showToast:false,
			success() {
				uni.showToast({
					title: '複制成功',
					icon: 'none'
				});
			}
		})
	}
}           

uniapp軟鍵盤撐起問題

點選input輸入框,整體頁面會上推,頂部自定義導航欄會頂跑不見了。

基于uniapp+vue3渲染markdown文法|軟鍵盤頂起問題

給輸入框外層加一個div,設定padding-bottom為鍵盤高度。

const fixPaddingBottom = computed(() => {
	let keyH = keyboardHeight.value > 70 ? keyboardHeight.value - 70 : keyboardHeight.value
	return (keyH || 10) + 'px'
})           
onMounted(() => {
	nextTick(() => {
		scrollToLast()
	})
	
	// #ifndef H5
	uni.onKeyboardHeightChange(e => {
		keyboardHeight.value = e.height
		// 在dom渲染完畢 滾動到最後一條消息
		nextTick(() => {
			scrollToLast()
		})
	})
	// #endif
})           

這樣基本就能解決鍵盤撐起問題了。

如果大家有其它解決方法,不妨一起交流讨論。

繼續閱讀