Vue实现一个textarea幽灵建议功能

不知道你有没有发现Bing AI聊天有个输入提示功能,在用户输入部分内容时后面会给出灰色提示文案。用户只要按下tab键就可以快速添加提示的后续内容。我将这个功能称为幽灵建议。接下来我将用Vue框架来实现这个功能。

布局样式

布局使用label标签作为容器,这样即使建议内容在上层,也不会影响输入框的输入。

html 复制代码
<label class="container">
  <textarea></textarea>
  <div class="ghost-content"></div>
</label>

样式需要确保输入框与建议内容容器除了颜色外都要一致。建议内容可以通过z-index: -1置于输入框底部,但要注意输入框必须是透明背景。

css 复制代码
.container {
  position: relative;
  display: block;
  width: 300px;
  height: 200px;
  font-size: 14px;
  line-height: 21px;
}
.container textarea {
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  font: inherit;
  color: #212121;
  background-color: #fff;
  outline: none;
}
.ghost-content {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  color: #212121;
  opacity: 0.3;
}

显示逻辑

显示逻辑比较简单,当输入框中显示输入内容时,找到匹配的内容后将其显示在建议容器中。以下是代码示例:

js 复制代码
import { ref } from 'vue'

const content = ref('') // 输入框内容
const ghostContent = ref('') // 建议内容
const suggestions = ['你好啊', '怎么学编程'] // 建议列表

const handleInput = () => {
  ghostContent.value = '' // 内容变化时,清空建议
  // 如果为空或者建议内容改变,则不进行后续匹配
  if (content.value === '') {
    return
  }
  const suggestion = suggestions.find((item) => item.startsWith(content.value))
  if (suggestion) {
    ghostContent.value = suggestion
  }
}

const handleTabKeydown = () => {
  // 监听tab键按下,将输入框内容设置为建议内容,同时清空建议内容
  content.value = ghostContent.value
  ghostContent.value = ''
}

按照以上代码的写法,已经可以实现幽灵建议的功能了。但还存在一个小问题,输入框内容和建议内容的重叠部分会显得比较粗。因此,最好将重叠部分的文字颜色设置为透明。我的解决方法是使用span标签来包裹重叠部分的内容,然后将span的文字样式设置为透明。此外,为了表示可以使用tab键,我在末尾添加了符号。改进后的代码如下:

js 复制代码
// 重复部分省略
// ...
const ghostHTML = ref('') // 建议内容HTML
const handleInput = () => {
  ghostContent.value = ''
  ghostHTML.value = ''
  if (content.value === '' || fromSuggestion) {
    fromSuggestion && (fromSuggestion = false)
    return
  }
  const suggestion = suggestions.find((item) => item.startsWith(content.value))
  if (suggestion) {
    ghostContent.value = suggestion
    ghostHTML.value = suggestion.replace(content.value, `<span>${content.value}</span>`) + ' →' // 显示内容替换
  }
}

const handleTabKeydown = () => {
  content.value = ghostContent.value
  ghostContent.value = ''
  ghostHTML.value = ''
}

最后,补充一下HTML代码。

html 复制代码
<label class="container">
  <textarea v-model="content" @input="handleInput" @keydown.tab.prevent="handleTabKeydown"></textarea>
  <div class="ghost-content" v-html="ghostHTML"></div>
</label>
  • 我们需要阻止tab按下的默认事件,按下tab键会导致切换到其他元素,使输入框失去焦点;
  • 使用v-html来绑定HTML内容。
相关推荐
安全系统学习1 小时前
系统安全之大模型案例分析
前端·安全·web安全·网络安全·xss
涛哥码咖1 小时前
chrome安装AXURE插件后无效
前端·chrome·axure
OEC小胖胖1 小时前
告别 undefined is not a function:TypeScript 前端开发优势与实践指南
前端·javascript·typescript·web
行云&流水2 小时前
Vue3 Lifecycle Hooks
前端·javascript·vue.js
Sally璐璐2 小时前
零基础学HTML和CSS:网页设计入门
前端·css
老虎06272 小时前
JavaWeb(苍穹外卖)--学习笔记04(前端:HTML,CSS,JavaScript)
前端·javascript·css·笔记·学习·html
三水气象台2 小时前
用户中心Vue3网页开发(1.0版)
javascript·css·vue.js·typescript·前端框架·html·anti-design-vue
灿灿121382 小时前
CSS 文字浮雕效果:巧用 text-shadow 实现 3D 立体文字
前端·css
烛阴2 小时前
Babel 完全上手指南:从零开始解锁现代 JavaScript 开发的超能力!
前端·javascript
AntBlack3 小时前
拖了五个月 ,不当韭菜体验版算是正式发布了
前端·后端·python