探索uniapp+vue3解析markdown语法|uniapp键盘撑起

最近正在尝试使用uniapp+vue3开发仿制chatgpt会话功能。


如上图:经过测试在h5/App端/小程序端 均支持markdown语法解析,键盘撑起后,整体页面和顶部自定义导航栏不会被顶起。

uniapp markdown解析及语法高亮

使用了markdown-ithighlight.js插件实现markdown语法解析及高亮代码。

// 引入uniapp markdown插件
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'

探索uniapp+vue3解析markdown语法|uniapp键盘撑起_第1张图片

  • 初始化markdown插件
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 '
  • + (index + 1) + '">' + item +'
  • '
    }).join('') html = '
      ' + html + '
    '
    // 代码复制 copyCode.push(str) let htmlCode = `
    ` // #ifndef MP-WEIXIN htmlCode += `` // #endif htmlCode += `
    ${html}
    `
    ; htmlCode += '
    '
    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
    }
    

    在会话消息地方调用parseNodes方法。

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

    uniapp中的rich-text组件提供了itemclick方法。拦截点击事件(只支持 a、img标签),返回当前node信息 event.detail={node}

    // 复制代码
    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'
    				});
    			}
    		})
    	}
    }
    

    到这里就基本上可以支持markdown语法解析了。

    探索uniapp+vue3解析markdown语法|uniapp键盘撑起_第2张图片

    uniapp 键盘撑起页面问题

    uniapp中使用flex布局一个聊天页面,input输入框随着键盘弹起,整个页面会被向上顶起,导致顶部导航栏会不见了。
    就想着能否在键盘弹起的时候,获取键盘高度,然后给弹起div层加个padding,经过一番尝试,此方案可行~~

    探索uniapp+vue3解析markdown语法|uniapp键盘撑起_第3张图片
    如上图:给编辑器外层加一个view层,设置 padding-bottom 为键盘弹起高度。

    const fixPaddingBottom = computed(() => {
    	let keyH = keyboardHeight.value > 70 ? keyboardHeight.value - 70 : keyboardHeight.value
    	return (keyH || 10) + 'px'
    })
    

    这里的70可以根据实际情况调整。

    然后在onMounted中获取键盘弹起高度。

    onMounted(() => {
    	nextTick(() => {
    		scrollToLast()
    	})
    	
    	// #ifndef H5
    	uni.onKeyboardHeightChange(e => {
    		keyboardHeight.value = e.height
    		// 在dom渲染完毕 滚动到最后一条消息
    		nextTick(() => {
    			scrollToLast()
    		})
    	})
    	// #endif
    })
    

    探索uniapp+vue3解析markdown语法|uniapp键盘撑起_第4张图片
    经过一番调试,键盘弹起,只是内容区被顶起,而顶部的自定义导航栏则不会被顶跑,完美解决了页面整体被顶跑的问题。

    如果大家有其它比较优的解决方法,欢迎一起交流讨论哈~~

    你可能感兴趣的:(uniapp+vue3,uniapp)