当前位置: 首页 > Web前端 > HTML

前端web实现(@、At、Aite)选人或引用数据

时间:2023-03-29 12:32:01 HTML

前言在我们日常的社交中,@XXX功能可以说是一个比较常见的功能。本文将结合实践介绍一种快速实现@选择或引用数据的方法。功能需求简单说一下需求:1、在输入框中输入@弹出浮窗,然后可以在浮窗中选择相关数据;2、在输入框中输入#弹出浮窗,然后在浮窗中可以选择数据相关数据;3、@和#引用的数据应该包括name和id等,最后传递给后端;4、删除@和#引用的数据时,需要整体删除;5、@和#需要引用的数据用不同的颜色标示。就是这样。对于技术方案,参考了网上很多大咖的文章,也大致了解了一些社交平台的实现方式。有兴趣的朋友可以参考文末的参考资料。最后因为功能和时间的契合,选择了开源库:tributejs。这个开源库有native、vue等例子,没有react的例子,不过问题不大,使用方法都差不多。本文中@XXX功能的具体实现是通过tributejs+React实现的,所以React技术栈的同学可以直接参考后面的例子,其他技术栈的同学可以参考tributejs的官方实现。@功能实现首先当然是下载tributejs:yarnaddtributejs或者npminstalltr??ibutejs然后引入tributejs配置需要的功能。各个配置的含义可以直接在tributejs的github上查看。最后,您可以向编辑器添加一些自定义样式:index.tsximportReact,{useEffect,useState,useRef}from'react';从“tributejs”导入贡品;导入“./index.less”;constAtDemo=()=>{const[atList,setAtList]=useState([{key:"1",value:"小明",position:"前端开发工程师"},{key:"2",value:"小李",position:"后端开发工程师"}]);const[poundList,setpoundList]=useState([{name:"JavaScript",explain:"前端开发语言"},{name:"Java",explain:"后端开发语言之一"}]);useEffect(()=>{renderEditor(atList,poundList);},[])constrenderEditor=(_atList:any[],_poundList:any[])=>{lettributeMultipleTriggers=newTribute({allowSpaces:true,noMatchTemplate:function(){returnnull;},collection:[{selectTemplate:function(item){if(this.range.isContentEditable(this.current.element)){return(`@${item.original.值}`);}return"@"+item.original?.value;},值:_atList,menuItemTemplate:function(item){returnitem.original.value;},},{trigger:"#",selectTemplate:function(item){if(this.range.isContentEditable(this.current.element)){return(`#${item.original.name}`);}return"#"+item.original.name;},值:_poundList,查找:“名称”,fillAttr:“名称”}]});tributeMultipleTriggers.attach(document.getElementById(“editorMultiple”)作为HTMLElement);}return(

)}exportdefaultAtDemo;index.less.at-demo{背景颜色:#fff;填充:24px;.at-item,.pound-item{颜色:#2ba6cb;}}.tribute-container{位置:绝对;顶部:0;左:0;高度:自动;溢出:自动;显示:块;z指数:999999;}.tribute-containerul{保证金:0;边距顶部:2px;填充:0;列表样式:无;背景:#fff;边框:1px实心#3c98fa;边界半径:4px;}.tribute-containerli{padding:5px5px;游标:指针;边界半径:4px;}.tribute-containerli.highlight{背景:#eee;}.tribute-containerlispan{字体粗细:粗体;}.tribute-containerli.no-match{cursor:default;}.tribute-container.menu-highlighted{字体粗细:粗体;}.tribute-demo-input{大纲:无;边框:1px实心#d9d9d9;填充:4px11px;边界半径:2px;字体大小:15px;最小高度:100px;cursor:text;}.tribute-demo-input:hover{border-color:#3c98fa;过渡:所有0.3秒;}.tribute-demo-input:focus{border-color:#3c98fa;}[contenteditable="true"]:empty:before{content:attr(placeholder);显示:块;颜色:#ccc;}#test-autocomplete-container{位置:相对;}#test-autocomplete-textarea-container{position:relative;}.float-right{float:right;}我们可以看到效果,还是很好的:引用的数据也被整体删除了:在编辑器中获取数据,我们输入在编辑器中最终获取到我们想要的数据并传递给后端:...import{Button}from'antd';//escapeHTMLconsthtmlEscape=(html:string)=>{returnhtml.replace(/[<>"&]/g,function(match,pos,originalText){switch(match){case"<":return"<";case">":return">"case"&":return"&";case"\"":return""";default:returnmatch;}});}constAtDemo=()=>{...constgetDataOfEditorMultiple=()=>{constchildrenData=document.getElementById('editorMultiple')?.innerHTML;console.log('childrenData',childrenData)consttoServiceData=htmlEscape(childrenData);console.log('toServiceData',toServiceData)}return(
获取输入框内所有元素
)}我们可以直接通过getDataOfEditorMultiple方法获取编辑器中的数据,转义后发送给后台,实时获取编辑器中引用的数据。有时我们可能需要实时监控编辑器中的数据,或者引用的数据。此时我们就可以调用oninput方法了。当然在其他情况下也可以调用onblur和onfocus这两个方法。顾名思义,它们是失去焦点时和获得焦点时。完整代码如下:importReact,{useEffect,useState,useRef}from'react';导入“./index.less”;从“tributejs”导入贡品;从'antd'导入{Button};consthtmlEscape=(html:string)=>{returnhtml.replace(/[<>"&]/g,function(match,pos,originalText){switch(match){case"<":return"<";case">":return">"case"&":return"&";case"\"":return""";default:returnmatch;}});}constAtDemo=()=>{const[atList,setAtList]=useState([{key:"1",value:"小明",position:"前端开发工程师"},{key:"2",value:"小李",position:"后端开发工程师"}]);const[poundList,setpoundList]=useState([{name:"JavaScript",explain:"前端开发语言之一"},{name:"Java",explain:"后端开发语言之一"}]);useEffect(()=>{renderEditor(atList,poundList);},[])constrenderEditor=(_atList:any[],_poundList:any[])=>{lettributeMultipleTriggers=newTribute({allowSpaces:true,noMatchTemplate:function(){returnnull;},collection:[{selectTemplate:function(item){if(this.range.isContentEditable(this.current.element)){return(`@${item.original.value}`);}return"@"+item.original?.value;},值:_atList,menuItemTemplate:function(item){returnitem.original.value;},},{trigger:"#",selectTemplate:function(item){if(this.range.isContentEditable(this.current.element)){return(`#${item.original.name}`);}return"#"+item.original.name;},值:_poundList,查找:“名称”,fillAttr:“名称”}]});tributeMultipleTriggers.attach(document.getElementById(“editorMultiple”)作为HTMLElement);}constgetDataOfEditorMultiple=()=>{constchildrenData=document.getElementById('editorMultiple')?.innerHTML||'';console.log('childrenData',childrenData)consttoServiceData=htmlEscape(childrenData);console.log('toServiceData',toServiceData)}constonInput=()=>{constatItemList=document.getElementsByClassName('at-item');Array.prototype.forEach.call(atItemList,function(el){console.log(el.dataset.atkey);console.log(el.dataset.atvalue);});}return(获取输入框中所有元素)}导出默认的AtDemo;几个关键点的实现下面是几个关键的功能点。特性;参考数据的浮窗定位可以通过Selection对象获取;@或#引用的数据,如果想一次性删除,可以在@或#引用的数据外加一个,表示不可编辑的标签;将引用的数据定义为特定的颜色,因为当我们在输入框中插入引用数据时,引用的数据被HTML标签包裹起来,所以我们只需要对相关的HTML进行样式设置即可;如果想获取引用数据中多个属性的值,可以使用HTML5自定义属性data-xxx来保存我们想要的属性,就像上面的例子值一样,然后获取我们要的属性的值想要通过遍历标签el.dataset.xxx。最后,本文介绍一个可以在前端快速实现@xxx选择或引用数据的功能,在某些场景下也算是比较好的解决方案。有兴趣的同学可以看看文末参考文章中其他大佬的实现方法。参考https://github.com/zurb/tributehttps://segmentfault.com/a/11...https://segmentfault.com/a/11...https://juejin.cn/post/698225...https://mp.weixin.qq.com/s/YP...