天天看点

基于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
})           

这样基本就能解决键盘撑起问题了。

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

继续阅读