900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > JS获取鼠标光标位置并在光标位置添加内容

JS获取鼠标光标位置并在光标位置添加内容

时间:2021-10-11 08:09:56

相关推荐

JS获取鼠标光标位置并在光标位置添加内容

目标需求

获取鼠标光标位置,然后点击按钮或其他事件,在鼠标光标的位置插入需要的文字等

准备工具

contenteditable:contenteditable属性指定元素内容是否可编辑。window.getSelection(): 获取鼠标光标位置window.getSelection().getRangeAt(params):getRangeAt把鼠标光标在的位置分成前后两端,getRangeAt得到的是一个数组,params通常是数组的下表,我们这里写0createRange():返回新创建的Range对象,可以用来表示文档的一个区域或与该文档相关的 DocumentFragment 对象。

HTML

react写法

<div id="contentTable" className={styles['infoBox']} placeholder='请输入内容' contentEditable suppressContentEditableWarning onblur={this.blurDiv} />

注意⚠️

当不写suppressContentEditableWarning这个属性的时候,有可能会抛出警告:Warning: A component iscontentEditableand containschildrenmanaged by React.

CSS

如果我们想给我div加一个placeholder的话,如下:

.infoBox {width: 100%;height: 115px;padding: 16px;line-height: 1;outline: none;&:empty::before {content: attr(placeholder);color: #808080;}}

JS

// 光标从id为content的div标签失焦的触发blurDivblurDiv = () => {const positionObj = window.getSelection().getRangeAt(0)// setState是react自带的api,这里把positionObj存起来,其他方法用的到this.setState({positionObj })}// 插入动作modalOk = () => {const {item } = this.state// item为要插入的相关信息this.insertFun(item)}// 插入某个位置insertFun = item => {const {positionObj } = this.state// contentWrap是拿到上面👆div的dom,react如果拿不到真实dom的话,可以用ref或者useRef获取真实的domconst contentWrap = document.getElementById('contentTable')const range = document.createRange()if (contentWrap.childNodes.length == 0) {contentWrap.appendChild(this.handleCreateContent(item))} else {// 这里判断positionObj是否为undefined,是因为第一添加的时候是undefined,第一次添加的时候直接insertNode到id为contentTable这个父节点if (positionObj == undefined) {range.setStart(contentWrap.childNodes[0], 0)range.setEnd(contentWrap.childNodes[0], 0)range.insertNode(this.handleCreateContent(item))return}range.setStart(positionObj.startContainer, positionObj.startOffset)range.setEnd(positionObj.startContainer, positionObj.startOffset)range.insertNode(this.handleCreateContent(item))}}// 处理要插入什么内容handleCreateContent = item => {const {dropMenuType, name, pagePath } = itemconst width = this.getTextWidth(`{${name}}`)const input = document.createElement('input')input.setAttribute('class', 'input')input.setAttribute('value', `{${name}}`)input.setAttribute('disabled', false)input.style.width = `${width + 5}px`input.style.border = 'none'return input}// 获取文字的宽度,因为input的宽度不能用width:fit-content自适应,并且这里用input标签的原因是因为想把要插入的内容当作一个整体(光标选不中input里面的内容,只能选input的前后)getTextWidth = str => {let dom = document.createElement('span')dom.setAttribute('id', 'textWidth')dom.style.display = 'inline-block'dom.textContent = strdocument.body.appendChild(dom)const w = document.getElementById('textWidth').clientWidthdocument.body.removeChild(document.getElementById('textWidth'))return w}// 最后,我们插入完,获取id为contentTable里面的内容getContent = () => {const contentWrap = document.getElementById("contentTable");// contentWrap.childNodes(数组的格式)里面就是我们要的数据,我们处理一下就可以了console.log(contentWrap.childNodes)}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。