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

news2024/7/6 19:39:11

最近正在尝试使用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'

在这里插入图片描述

  • 初始化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 '<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
}

在会话消息地方调用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 键盘撑起页面问题

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

在这里插入图片描述
如上图:给编辑器外层加一个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
})

在这里插入图片描述
经过一番调试,键盘弹起,只是内容区被顶起,而顶部的自定义导航栏则不会被顶跑,完美解决了页面整体被顶跑的问题。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/676485.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入理解深度学习——BERT(Bidirectional Encoder Representations from Transform):输入表示

分类目录&#xff1a;《深入理解深度学习》总目录 BERT在预训练阶段使用了《深入理解深度学习——BERT&#xff08;Bidirectional Encoder Representations from Transform&#xff09;&#xff1a;MLM&#xff08;Masked Language Model&#xff09;》和《深入理解深度学习——…

C++——函数重载

目录 1. 函数重载的概念 2. 函数重载注意点 3. C可以函数重载的原因 4. 总结 1. 函数重载的概念 函数重载:是函数的一种特殊情况。C语言不支持函数重载&#xff0c;而C允许在同一作用域中声明几个功能类似的同名函数&#xff0c;这些同名函数的形参列表(参数个数 或 类型 …

【软件设计师暴击考点】软件工程知识高频考点【一】

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;软件…

基于Springboot+vue的汽车租赁系统设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

阿里云服务器的可用区和地域选择有哪些考虑因素?如何优化性能?

阿里云服务器的可用区和地域选择有哪些考虑因素&#xff1f;如何优化性能&#xff1f;   选择阿里云服务器时&#xff0c;可用区和地域选择是一个非常关键的环节。本文将为您详细解析在这个过程中需要考虑的因素以及如何优化性能。 一、阿里云服务器的可用区和地域选择的考虑…

PHP基础知识解析:探索PHP编程的核心概念和技巧

目录 PHP简介 什么是PHP 网站基本概念 网站 静态网站特点 动态网站特点 服务器概念 IP 域名 DNS 端口 PHP基础知识 PHP语法 PHP注释 PHP语句分隔符 变量 变量基本概念 变量的使用 命名的命名规则&#xff1a; 预定义变量&#xff1a; 可变变量 变量传值 …

【Linux操作系统】共享内存

文章目录 什么是共享内存&#xff1f;共享内存的原理共享内存的知识点构建创建共享内存的前提-key值共享内存的创建ipcs命令共享内存的释放共享内存的关联与解除代码演示共享内存的大小共享内存的特点 什么是共享内存&#xff1f;共享内存的原理 共享内存让不同进程看到同一份…

C++ --引用与函高级

引用 定义&#xff1a;给变量起别名。 语法&#xff1a;数据类型&别名原名。 int a10; int &ba; //(此时的a和b都指向了同一块空间&#xff0c;都可对里面的元素进行修改) 对这两个变量名字任意一个进行修改&#xff0c;两变量的结果都会发生变化 引用注意事项 1.引…

211大学,4个计算机应届生,真实求职情况~

每年6月&#xff0c;毕业就业是一个绕不开的永恒话题&#xff01;2024届秋招即将开始&#xff0c;你们都找到工作了吗&#xff1f;是否还在犹豫、焦虑、没有头绪…… 先知先觉的那一批人&#xff0c;总会未雨绸缪&#xff0c;从前辈那里汲取经验。 播妞采访了4位211计算机应届…

vue+leaflet笔记之地图放大镜

vueleaflet笔记之地图放大镜 文章目录 vueleaflet笔记之地图放大镜开发环境使用教程安装依赖库使用简介 详细源码(Vue3) 本文介绍了Web端使用 Leaflet开发库显示地图放大镜的方法 (底图来源:中科星图)&#xff0c;结合 leaflet.magnifyingglass插件可以为Leaflet图层添加“放…

SHAP显示原始特征

1.问题描述 SHAP用于特征解释&#xff0c;对于机器学习方法往往需要对原始特征进行编码&#xff0c;而SHAP在绘制单个样本时&#xff0c;会显示每个特征及其取值&#xff0c;而这个取值已经是编码后的&#xff0c;通常无法确定其含义。如&#xff1a; 下图所示的拍卖公司、城市…

【软件设计师暴击考点】数据结构高频考点暴击系列

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;软件…

MarkDown语法学习 —— LaTex数学公式 数学符号

文章目录 01 | &#x1f6d1; LaTex公式模式02 | &#x1f6a6;上下标符号 & 数学符号03 | &#x1f6a5; 运算符 LaTeX&#xff0c;作为广义上的计算机标记语言&#xff08;比如HTML&#xff09;&#xff0c;它继承了计算机语言的光荣传统&#xff0c;通过一些简单的代码表…

入门防火墙基本原理

防火墙是可信和不可信网络之间的一道屏障&#xff0c;通常用在LAN和WAN之间。它通常放置在转发路径中&#xff0c;目的是让所有数据包都必须由防火墙检查&#xff0c;然后根据策略来决定是丢弃或允许这些数据包通过。例如&#xff1a; 如上图&#xff0c;LAN有一台主机和一台交…

Nginx基础配置以及实操

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、nginx主配置文件1.全局配置2.I/O事件配置3.HTTP配置4.检查文件是否配置正确5.浏览器测试6.总配置文件图示6.1 nginx总配置文件的三个模块6.2 HTTP文件配置的图示…

通过Python+Selenium获取我的所有文章质量分

文章目录 前言一、背景二、设计三、环境准备四、开发1.查询文章数量1.1请求url1.2响应结果1.3代码 2.获取每页文章列表2.1请求url2.2响应结果 3.获取所有文章url3.1代码 4.保存excle方法4.1代码 5.查询所有文章质量分并写入excle5.1代码 6.程序入口6.1代码 7.需要引入的模块 五…

Copilot是GPT的理想应用模式吗?

自OpenAI发布ChatGPT以来&#xff0c;LLM持续火热&#xff0c;各大公司纷纷入场。但近一段时间以来&#xff0c;我观测到的LLM应用场景&#xff0c;基本都是Copilot的形式&#xff0c;即以对话为基础的辅助应用。尽管体验起来十分的高大上&#xff0c;但我能明确感受到&#xf…

微信小程序发布上线全流程 注册 开发 上传审核

微信小程序接入全流程 微信小程序从零到上线&#xff0c;要经历小程序账号注册开通、完善小程序信息、开发小程序、提交小程序审核及发布四个过程&#xff1a; 以下是微信小程序发布上线的详细流程&#xff1a; 确认小程序信息&#xff1a;在微信公众平台注册并登录后&#…

【C语言进阶】预处理那些事儿

文章目录 &#x1f4d6;预定义符号&#x1f4d6;预处理指令&#x1f4d6;#define &#x1f516;#define定义标识符&#x1f516;#define定义宏&#x1f516;#define替换规则&#x1f516;#和##&#x1f516;带有副作用的宏参数&#x1f516;宏和函数的对比&#x1f516;命名约定…

正点原子 STM32F4/F7水星 开发板资料连载第二十一章LTDC LCD实验

正点原子 STM32F4/F7水星 开发板资料连载第二十一章LTDC LCD实验 - 知乎 (zhihu.com) 本章我们将通过 STM32F767 的 LTDC 接口来驱动 RGBLCD 的显示&#xff0c;另外&#xff0c;STM32F767 的 LTDC 还有DMA2D 图形加速&#xff0c;我们也顺带进行介绍。本节分为三个部分&#…