chatgpt의 타자기 효과를 구현한 vue3의 상세 예시
在做 chatgpt 镜像站的时候,发现有些镜像站是没做打字机的光标效果的,就只是文字输出,是他们不想做吗?反正我想做。于是我仔细研究了一下,实现了打字机效果加光标的效果,现在分享一下我的解决方案以及效果图
共识
首先要明确一点,chatgpt 返回的文本格式是 markdown 的,最基本的渲染方式就是把 markdown 文本转换为 HTML 文本,然后 v-html
渲染即可。这里的转换和代码高亮以及防 XSS 攻击用到了下面三个依赖库:
- marked 将markdwon 转为 html
- highlight 处理代码高亮
- dompurify 防止 XSS 攻击
同时我们是可以在 markdown 中写 html 元素的,这意味着我们可以直接把光标元素放到最后!
将 markdown 转为 html 并处理代码高亮
先贴代码
MarkdownRender.vue
<script setup> import {computed} from 'vue'; import DOMPurify from 'dompurify'; import {marked} from 'marked'; import hljs from '//cdn.staticfile.org/highlight.js/11.7.0/es/highlight.min.js'; import mdInCode from "@/utils/mdInCode"; // 用于判断是否显示光标 const props = defineProps({ // 输入的 markdown 文本 text: { type: String, default: "" }, // 是否需要显示光标?比如在消息流结束后是不需要显示光标的 showCursor: { type: Boolean, default: false } }) // 配置高亮 marked.setOptions({ highlight: function (code, lang) { try { if (lang) { return hljs.highlight(code, {language: lang}).value } else { return hljs.highlightAuto(code).value } } catch (error) { return code } }, gfmtrue: true, breaks: true }) // 计算最终要显示的 html 文本 const html = computed(() => { // 将 markdown 转为 html function trans(text) { return DOMPurify.sanitize(marked.parse(text)); } // 光标元素,可以用 css 美化成你想要的样子 const cursor = '<span></span>'; if (props.showCursor) { // 判断 AI 正在回的消息是否有未闭合的代码块。 const inCode = mdInCode(props.text) if (inCode) { // 有未闭合的代码块,不显示光标 return trans(props.text); } else { // 没有未闭合的代码块,将光标元素追加到最后。 return trans(props.text + cursor); } } else { // 父组件明确不显示光标 return trans(props.text); } }) </script> <template> <!-- tailwindcss:leading-7 控制行高为1.75rem --> <div v-html="html" class="markdown leading-7"> </div> </template> <style> /** 设置代码块样式 **/ .markdown pre { @apply bg-[#282c34] p-4 mt-4 rounded-md text-white w-full overflow-x-auto; } .markdown code { width: 100%; } /** 控制段落间的上下边距 **/ .markdown p { margin: 1.25rem 0; } .markdown p:first-child { margin-top: 0; } /** 小代码块样式,对应 markdown 的 `code` **/ .markdown :not(pre) > code { @apply bg-[#282c34] px-1 py-[2px] text-[#e06c75] rounded-md; } /** 列表样式 **/ .markdown ol { list-style-type: decimal; padding-left: 40px; } .markdown ul { list-style-type: disc; padding-left: 40px; } /** 光标样式 **/ .markdown .cursor { display: inline-block; width: 2px; height: 20px; @apply bg-gray-800 dark:bg-gray-100; animation: blink 1.2s step-end infinite; margin-left: 2px; vertical-align: sub; } @keyframes blink { 0% { opacity: 1; } 50% { opacity: 0; } 100% { opacity: 1; } } </style>
可以发现最基本的 markdown 显示还是挺简单的,话就不多说了,都在注释里。
我想你也许对判断消息中的代码块是否未闭合更感兴趣,那么就继续看下去吧!
代码块是否未闭合
markdown 有两种代码块,一种是 `code` ,另一种是 " code ",我叫他小代码块和大代码块。
一开始我是想用正则去判断的,但是奈何有点复杂,我实在想不出应该如何去编写正则,让 chatgpt 写的正则也会判断失败,而且还要考虑到转义符,就算写出了正则,估计也会很复杂和难以维护。
经过短暂的苦思冥想后,我想到了之前在 《Vue.js设计与实现》 中看到的用有限元状态机解析 html 文本的方案。
这里有请 chatgpt 简单介绍一下有限元状态机:
有限元状态机(finite element state machine)是一种基于状态机的建模技术,它可以将系统的行为描述为一组状态和状态之间的转换。每个状态可以对应系统内的一种状态,而状态之间的转换则表示系统内部的转换过程。有限元状态机还可以用于系统的可靠性分析和测试,同时也可以作为软件工程中的一种建模工具,帮助代码实现、测试和调试等方面。
在实际应用中,有限元状态机通常是通过自动化工具生成,并且可以用于控制系统、网络通信协议、软件接口等方面的设计和测试。由于有限元状态机具有自动化生成和完备性检查等优点,因此它已经成为了一种广泛应用的建模与测试工具。
请站在web前端的视角下进行介绍
从前端开发的角度来看,有限元状态机可以用于构建复杂的交互式Web应用程序。在Web应用程序中,有限元状态机可以描述用户界面的不同状态(例如,登录、注册、未登录等),以及状态之间的转换(例如,从登录状态转换到注册状态)。
通常情况下,前端工程师使用JavaScript实现有限元状态机,包括定义状态、定义状态之间的转换规则、处理状态转换时的行为等。使用有限元状态机可以帮助前端工程师更好地掌控应用程序的状态,从而减少代码中的复杂条件分支和无法预测的行为。同时,有限元状态机也可以帮助前端团队共同理解应用程序的状态和转换规则,从而更好地协作开发和维护Web应用程序。
总之,有限元状态机是一种非常有用的前端开发技术,可以帮助前端工程师更好地构建和管理Web应用程序的状态和行为,提高应用程序的可靠性和用户体验。
回到正题,我可以一点一点的从头开始去解析 markdown 文本。想象这么一个简单的状态转换流程:
- 初始状态为文本状态。
- 遇到代码块标记,文本状态转换到代码块开始状态。
- 再次遇到代码块标记,从代码块开始状态转换到文本状态。
不过现实要更复杂一点,我们有小代码块和大代码块。有限元状态机的妙处就在这里,当处在小代码块状态的时候,我们不需要操心大代码块和正常文本的事,他的下一个状态只能是遇到小代码块的闭合标签,进入文本状态。
理解了这些,再来看我的源码,才会发现他的精妙。
const States = { text: 0, // 文本状态 codeStartSm: 1, // 小代码块状态 codeStartBig: 2, // 大代码块状态 } /** * 判断 markdown 文本中是否有未闭合的代码块 * @param text * @returns {boolean} */ function isInCode(text) { let state = States.text let source = text let inStart = true // 是否处于文本开始状态,即还没有消费过文本 while (source) { // 当文本被解析消费完后,就是个空字符串了,就能跳出循环 let char = source.charAt(0) // 取第 0 个字 switch (state) { case States.text: if (/^\n?```/.test(source)) { // 以 ``` 或者 \n``` 开头。表示大代码块开始。 // 一般情况下,代码块前面都需要换行。但是如果是在文本的开头,就不需要换行。 if (inStart || source.startsWith('\n')) { state = States.codeStartBig } source = source.replace(/^\n?```/, '') } else if (char === '\\') { // 遇到转义符,跳过下一个字符 source = source.slice(2) } else if (char === '`') { // 以 ` 开头。表示小代码块开始。 state = States.codeStartSm source = source.slice(1) } else { // 其他情况,直接消费当前字符 source = source.slice(1) } inStart = false break case States.codeStartSm: if (char === '`') { // 遇到第二个 `,表示代码块结束 state = States.text source = source.slice(1) } else if (char === '\\') { // 遇到转义符,跳过下一个字符 source = source.slice(2) } else { // 其他情况,直接消费当前字符 source = source.slice(1) } break case States.codeStartBig: if (/^\n```/.test(source)) { // 遇到第二个 ```,表示代码块结束 state = States.text source = source.replace(/^\n```/, '') } else { // 其他情况,直接消费当前字符 source = source.slice(1) } break } } return state !== States.text } export default isInCode
到这里,就已经实现了一个 chatgpt 消息渲染了。喜欢的话点个赞吧!谢谢!
위 내용은 chatgpt의 타자기 효과를 구현한 vue3의 상세 예시의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











DALL-E 3는 이전 모델보다 대폭 개선된 모델로 2023년 9월 공식 출시되었습니다. 복잡한 디테일의 이미지를 생성할 수 있는 현재까지 최고의 AI 이미지 생성기 중 하나로 간주됩니다. 그러나 출시 당시에는 제외되었습니다.

설치 단계: 1. ChatGTP 공식 웹사이트 또는 모바일 스토어에서 ChatGTP 소프트웨어를 다운로드합니다. 2. 이를 연 후 설정 인터페이스에서 언어를 중국어로 선택합니다. 3. 게임 인터페이스에서 인간-기계 게임을 선택하고 설정합니다. 4. 시작한 후 채팅 창에 명령을 입력하여 소프트웨어와 상호 작용합니다.

PHP와 Vue: 프론트엔드 개발 도구의 완벽한 조합 오늘날 인터넷이 빠르게 발전하는 시대에 프론트엔드 개발은 점점 더 중요해지고 있습니다. 사용자가 웹 사이트 및 애플리케이션 경험에 대한 요구 사항이 점점 더 높아짐에 따라 프런트 엔드 개발자는 보다 효율적이고 유연한 도구를 사용하여 반응형 및 대화형 인터페이스를 만들어야 합니다. 프론트엔드 개발 분야의 두 가지 중요한 기술인 PHP와 Vue.js는 함께 사용하면 완벽한 도구라고 볼 수 있습니다. 이 기사에서는 독자가 이 두 가지를 더 잘 이해하고 적용할 수 있도록 PHP와 Vue의 조합과 자세한 코드 예제를 살펴보겠습니다.

chatgpt는 중국에서는 사용할 수 있지만 등록할 수 없으며, 홍콩, 마카오에서는 등록을 원하는 경우 외국 휴대폰 번호를 사용하여 등록할 수 있습니다. 등록 과정에서 네트워크 환경을 전환해야 합니다. 외국 IP로.

프론트엔드 개발 인터뷰에서 일반적인 질문은 HTML/CSS 기초, JavaScript 기초, 프레임워크 및 라이브러리, 프로젝트 경험, 알고리즘 및 데이터 구조, 성능 최적화, 크로스 도메인 요청, 프론트엔드 엔지니어링, 디자인 패턴, 새로운 기술 및 트렌드. 면접관 질문은 후보자의 기술적 능력, 프로젝트 경험, 업계 동향에 대한 이해를 평가하기 위해 고안되었습니다. 따라서 지원자는 자신의 능력과 전문성을 입증할 수 있도록 해당 분야에 대한 충분한 준비를 갖추어야 합니다.

Django는 빠른 개발과 깔끔한 방법을 강조하는 Python으로 작성된 웹 애플리케이션 프레임워크입니다. Django는 웹 프레임워크이지만 Django가 프런트엔드인지 백엔드인지에 대한 질문에 답하려면 프런트엔드와 백엔드의 개념에 대한 깊은 이해가 필요합니다. 프론트엔드는 사용자가 직접 상호작용하는 인터페이스를 의미하고, 백엔드는 HTTP 프로토콜을 통해 데이터와 상호작용하는 서버측 프로그램을 의미합니다. 프론트엔드와 백엔드가 분리되면 프론트엔드와 백엔드 프로그램을 독립적으로 개발하여 각각 비즈니스 로직과 인터랙티브 효과, 데이터 교환을 구현할 수 있습니다.

C# 개발자로서 우리의 개발 작업에는 일반적으로 프런트엔드와 백엔드 개발이 포함됩니다. 기술이 발전하고 프로젝트의 복잡성이 증가함에 따라 프런트엔드와 백엔드의 공동 개발이 점점 더 중요해지고 복잡해졌습니다. 이 문서에서는 C# 개발자가 개발 작업을 보다 효율적으로 완료하는 데 도움이 되는 몇 가지 프런트 엔드 및 백엔드 공동 개발 기술을 공유합니다. 인터페이스 사양을 결정한 후 프런트엔드와 백엔드의 공동 개발은 API 인터페이스의 상호 작용과 분리될 수 없습니다. 프론트엔드와 백엔드 협업 개발이 원활하게 진행되기 위해서는 가장 중요한 것은 좋은 인터페이스 사양을 정의하는 것입니다. 인터페이스 사양에는 인터페이스 이름이 포함됩니다.

오픈AI(Open AI)가 드디어 검색에 본격 진출한다. 샌프란시스코 회사는 최근 검색 기능을 갖춘 새로운 AI 도구를 발표했습니다. 올해 2월 The Information에서 처음 보고한 새로운 도구는 SearchGPT라고 불리며
