记录一个需求,多行输入框 #变色输入话题,特殊符号,空格结束变色,且支持话题文字修改和删除,复制粘贴,限长500字,超出提示
js template div classbox p v-ifp classp请输入标题.../p div langzh-CN classdiv :contenteditablebox refeditor bluronBlur compositionstartonInput1(false) compositionendonInput1(true) inputonInput2(true) clickclick keyup.upgetData keyup.leftgetData keyup.rightgetData keyup.downgetData /div span classpos{{ string1.length }}/{{ textLength }}/span div classadd clickcar(#)# 添加话题/div /div /template script export default { name: RichText, data() { return { p: true, box: true, divspan: , string1: , // 内容 index: 0, // 光标位置 textLength: 500, // 文本的最大长度 list: [], // 内容中的关键词列表 kg: true, // 当前是否使用输入法输入 ischange: false, }; }, props: { value: { type:String, default: }, }, watch: { string1() { if (this.string1.length ! 0) { this.p false; } else { this.p true; } }, value: { handler: function (newValue, oldValue) { //判断赋值展示 this.$nextTick(() { const div this.$refs.editor; div.innerHTML newValue.videoName; this.onInput(true); }); }, deep: true, }, }, mounted() { this.getFocusPosition(); if (this.nameVideo?.videoName) { this.car(this.nameVideo.videoName); } }, methods: { // 使用上下左右按键在输入框中移动时需要获取光标的位置 getData(data) { this.index this.getFocusPosition(); }, // 每次点击div就重新获取一次当前光标的位置 click(a) { this.index this.getFocusPosition(); }, // 失去焦点触发传值,value是传进来的值 onBlur() { this.ischange true; this.uploadVideo.videoName this.string1; }, model() {}, // 使用delete按键删除 部分删减还没有全部实现还是出现跨标题的bug后续有空慢慢修复这个事件没啥用删除掉前面的bug就没了 handleDelete(event) { event.preventDefault(); const div this.$refs.editor; const text this.$refs.editor.innerText; const selection window.getSelection(); const selectedText selection.toString(); if (selectedText selectedText text) { div.innerHTML ; this.string1 ; this.index 0; this.onInput(true); return; } if (selectedText selectedText text) { div.innerHTML ; this.string1 ; this.index 0; this.onInput(true); return; } if (selectedText selectedText.indexOf(\n) -1) { let aa ; if ( this.index - selectedText.length this.index text.slice(this.index - selectedText.length, this.index) selectedText ) { aa text.slice(0, this.index - selectedText.length) text.slice(this.index); this.index this.index - selectedText.length; div.innerHTML aa; this.string1 this.$refs.editor.innerText; return this.onInput(true); } if ( this.index selectedText.length this.index text.slice(this.index, this.index selectedText.length) selectedText ) { aa text.slice(0, this.index) text.slice(this.index selectedText.length, text.length); div.innerHTML aa; this.string1 this.$refs.editor.innerText; return this.onInput(true); } div.innerHTML aa; this.string1 this.$refs.editor.innerText; this.onInput(true); return; } if (this.index 0) { const aa text.slice(0, this.index - 1) text.slice(this.index); div.innerHTML aa; this.string1 this.$refs.editor.innerText; this.index--; this.onInput(true); } }, //插入文本 car(zfc) { let le this.textLength - this.string1.length; if ((this.textLength this.string1.length this.string1.length 0) || le zfc.length) { this.$message({ type: error, message: 文字长度最大不超过500, }); return; } const index this.index; let arr this.string1.split(); arr.splice(index, 0, ...zfc.split()); const div this.$refs.editor; div.innerHTML arr.join(); this.index zfc.length; this.onInput(true, true); }, // 每次输入都会触发 onInput2(i) { const div this.$refs.editor; this.index this.getFocusPosition(); this.string1 this.$refs.editor.innerText; if (this.textLength this.string1.length this.string1.length 0 this.kg) { this.$message({ type: error, message: 文字长度最大不超过500, }); div.innerHTML this.string1.slice(0, this.textLength); div.blur(); } if (i this.kg) { this.onInput(i); } this.ischange true; this.uploadVideo.videoName this.string1; }, // 判断当前输入是否使用输入法 onInput1(e) { if (e) { this.kg true; if (this.textLength this.string1.length this.string1.length 0 this.kg) { const div this.$refs.editor; this.$message({ type: error, message: 文字长度最大不超过500, }); div.innerHTML this.string1.slice(0, this.textLength); div.blur(); } } else { this.kg false; } if (this.kg) { this.onInput(this.kg); } }, // 匹配关键词使用text替换e是否执行替换j暂时无用 onInput(e, j) { let text this.$refs.editor.innerText; this.string1 text; const re /#[^\s.,;?!。’、](?[\s.,;?!。’、])|#[^\s]/g; const newArr text.match(re); let matches newArr newArr.map((item) item.replace(/^#/, #)).sort((a, b) b.length - a.length); matches matches.forEach((item, i) { if (item #) { matches.splice(i, 1); } matches[i] item.slice(item.lastIndexOf(#), item.length); }); this.list matches; let div this.$refs.editor; if (matches e) { for (let i 0; i matches.length; i) { const match matches[i]; const regex new RegExp(${match}(?[\\s.,;?!。’、]|$)); text text.replace(regex, text classspan refspan$/text); div.innerHTML text; } } // 定位焦点光标 const range document.createRange(); const sel window.getSelection(); let index this.index; for (let i 0; i div.childNodes.length; i) { if (index div.childNodes[i].textContent.length) { index index - div.childNodes[i].textContent.length; } else { if (div.childNodes[i].className span) { range.setStart(div.childNodes[i].childNodes[0], index); } else { range.setStart(div.childNodes[i], index); } range.collapse(true); sel.removeAllRanges(); sel.addRange(range); return; } } }, // 获取光标位置 getFocusPosition() { const selection window.getSelection(); const range document.createRange(); selection.anchorNode range.setStart(selection.anchorNode, 0); const textNodes this.getTextNodes(this.$refs.editor); let index 0; // 遍历每一个文本节点 for (let i 0; i textNodes.length; i) { const textNode textNodes[i]; const length textNode.textContent.length; if (textNode selection.anchorNode) { index selection.anchorOffset; break; } index length; } return index; }, // 获取到每一个子节点 getTextNodes(node) { const textNodes []; if (node.nodeType Node.TEXT_NODE) { textNodes.push(node); } else { const children node.childNodes; for (let i 0; i children.length; i) { const child children[i]; textNodes.push(...this.getTextNodes(child)); } } return textNodes; }, } }; /script style .div { width: 580px; height: 115px; padding: 5px 15px; line-height: 16px; /* border: 1px #ccc transparent; */ overflow: auto; z-index: 999; border-radius: 4px; -webkit-user-modify: read-write-plaintext-only; } .div::-webkit-scrollbar { display: none; /* Chrome Safari */ } .p { position: absolute; top: 0px; left: 20px; color: #d3d1d1; z-index: -999999; } .span { color: #4f72f6; } .box { width: 600px; height: 106px; position: relative; padding-bottom: 40px; border: 1px #ccc solid; border-radius: 4px; } .pos { position: absolute; color: #ccc; bottom: 3px; right: 20px; } .colorred { color: #fe5353; } .add { width: 92px; margin-top: 25px; font-weight: 400; font-size: 14px; line-height: 24px; color: #4f72f6; background: #f0f3ff; border-radius: 4px; text-align: center; } .add:hover { background-color: #4f72f6; color: #f0f3ff; cursor: pointer; } /style

相关新闻

DS4Windows完整指南:5分钟让PS手柄在Windows上畅玩所有游戏

DS4Windows完整指南:5分钟让PS手柄在Windows上畅玩所有游戏

DS4Windows完整指南:5分钟让PS手柄在Windows上畅玩所有游戏 【免费下载链接】DS4Windows Like those other ds4tools, but sexier 项目地址: https://gitcode.com/gh_mirrors/ds/DS4Windows 还在为Windows游戏不兼容PlayStation手柄而烦恼吗?每次…

2026/9/30 8:28:28 阅读更多 →
相机位姿估计:PnP问题原理与工程实践

相机位姿估计:PnP问题原理与工程实践

1. 相机位姿估计的核心原理与应用场景在计算机视觉和机器人定位领域,相机位姿估计是一个基础但至关重要的技术。简单来说,就是通过图像信息计算出相机在三维空间中的位置和朝向。这个技术在我们日常生活中其实无处不在——从手机AR贴纸到自动驾驶车辆的定…

2026/9/29 12:51:22 阅读更多 →
微信小程序数据可视化终极指南:5分钟掌握echarts-for-weixin完整教程

微信小程序数据可视化终极指南:5分钟掌握echarts-for-weixin完整教程

微信小程序数据可视化终极指南:5分钟掌握echarts-for-weixin完整教程 【免费下载链接】echarts-for-weixin 基于 Apache ECharts 的微信小程序图表库 项目地址: https://gitcode.com/gh_mirrors/ec/echarts-for-weixin 还在为微信小程序中的数据展示而烦恼吗…

2026/9/30 3:54:45 阅读更多 →

最新新闻

IPD落地推不动?产品线模式才是组织底座与投资决策关键

IPD落地推不动?产品线模式才是组织底座与投资决策关键

最近连续被好几家正在推进IPD的企业问到同一个问题:流程文件、评审模板、项目立项标准全都搭起来了,管理层也很重视,可产品开发项目还是推不动,跨部门沟通依旧靠刷脸,该打的仗打不赢。聊到后面,基本都会落在…

2026/9/30 12:09:03 阅读更多 →
新浪微博架构演进:高并发微服务与Feed流设计深度解析

新浪微博架构演进:高并发微服务与Feed流设计深度解析

做后端这么久,我一直觉得新浪微博架构是最值得反复研究的系统之一。它不是一个教科书式的整洁架构,而是一部在高并发、高热点、海量数据下被逼出来的演化史。从早期一台数据库撑起千万用户的单体应用,到后来颇具代表性的微服务、推拉结合Feed…

2026/9/30 12:09:03 阅读更多 →
IPD落地为何必须配套产品线模式:组织形态决定流程成败

IPD落地为何必须配套产品线模式:组织形态决定流程成败

IPD这三年的热度一直没降过,但真正让我觉得值得聊的,不是流程文件写了多少,而是组织形态怎么跟着变。很多企业拿着华为的IPD模板改了一轮,评审会开了、文档模板上了、重量级团队也挂了牌,到头来研发还是围着功能部门转…

2026/9/30 12:09:03 阅读更多 →
hindsight经验回放:强化学习中的失败样本如何成为学习燃料

hindsight经验回放:强化学习中的失败样本如何成为学习燃料

1. 项目概述:"hindsight"到底在说什么第一次看到 "hindsight" 这个词,是在一个机器人抓取项目的实验记录里。当时我还以为是什么新出的框架名字,翻了一圈才发现,这个词本身就是核心——后见之明。中文语境里有…

2026/9/30 12:09:03 阅读更多 →
纯前端Excel表格:Luckysheet与LuckyExcel导入导出实战

纯前端Excel表格:Luckysheet与LuckyExcel导入导出实战

前几天有个做工艺的朋友找我,说车间每天要从设备上倒一批测量数据出来,格式是 CSV 和 Excel 混着来,同事想在浏览器里直接打开、随手改几个公式核一下数、再导出去发给别人。要求就三条:数据不能上服务器,界面得长得像…

2026/9/30 12:09:03 阅读更多 →
线性回归:从机器学习基础到特征工程与梯度下降的完整实践指南

线性回归:从机器学习基础到特征工程与梯度下降的完整实践指南

聊线性回归之前,先讲个背景。如果你刚接触机器学习,有个概念听过最多:线性回归、机器学习、特征、输出变量。这几个词几乎出现在所有入门教程、期末复习资料和面试题里,但很多人学了几天就把它当成“一个求直线的公式”&#xff0…

2026/9/30 12:07:57 阅读更多 →

日新闻

Base64 图片头部特征识别:从文件头到格式判断的完整指南

Base64 图片头部特征识别:从文件头到格式判断的完整指南

1. 项目概述:为什么说看懂 base64 图片头部是基本功这几年跟 base64 打交道的机会越来越多,后端接口返回图片、前端渲染验证码、小程序里存小图、还有一些老系统导出报表,动不动就给你一段长到怀疑人生的 base64 字符串。很多人拿到字符串就直…

2026/9/30 0:00:35 阅读更多 →
Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

简介:本资源是一份面向Java初学者与课程设计学生的公交站牌广告灯箱管理系统毕业设计文档,聚焦城市公共广告资源信息化管理痛点,提供从需求分析到技术实现的完整方案。文档采用标准学术论文结构,含摘要、英文摘要、目录及五章正文…

2026/9/30 0:00:35 阅读更多 →
用 Redis Lua 构建大模型 API 多租户原子配额治理体系

用 Redis Lua 构建大模型 API 多租户原子配额治理体系

我去年年底接了一个内部 AI 平台的治理需求,背景很直接:公司把 DeepSeek、MiniMax 这类大模型 API 统一封装成内部网关,开放给几个业务团队用。结果第一个月账单出来,额度直接超了 4 倍。仔细查日志,发现原因并不复杂—…

2026/9/30 0:00:35 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/29 8:16:59 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/29 16:41:41 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/9/29 8:24:48 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/29 19:29:29 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/29 5:58:00 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/29 3:55:56 阅读更多 →