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

目标需求

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

准备工具

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

HTML

react写法

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

注意⚠️

  • 当不写suppressContentEditableWarning这个属性的时候,有可能会抛出警告:Warning: A component is contentEditable and contains children managed 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标签失焦的触发blurDiv
	blurDiv = () => {
		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获取真实的dom
		const 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 } = item
			const 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 = str
		document.body.appendChild(dom)
		const w = document.getElementById('textWidth').clientWidth
		document.body.removeChild(document.getElementById('textWidth'))
		return w
	}
	// 最后,我们插入完,获取id为contentTable里面的内容
	getContent = () => {
		 const contentWrap = document.getElementById("contentTable");
		 // contentWrap.childNodes(数组的格式)里面就是我们要的数据,我们处理一下就可以了
		 console.log(contentWrap.childNodes)
	}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Vue中获取`div`元素的光标位置,可以使用`Selection`对象和`Range`对象。下面是一个示例: 首先,在Vue组件的模板中,给`div`元素添加一个`ref`属性: ```html <template> <div ref="myDiv" contenteditable="true" @mouseup="handleMouseUp"></div> </template> ``` 然后,在Vue组件的方法中,定义一个`handleMouseUp`方法来鼠标抬起事件。在该方法中,可以通过`window.getSelection()`获取光标位置,并使用`Range`对象获取光标相对于`div`元素的偏移量: ```javascript <script> export default { methods: { handleMouseUp() { const selection = window.getSelection(); const range = selection.getRangeAt(0); const divOffset = this.$refs.myDiv.getBoundingClientRect(); const { top, left } = range.getBoundingClientRect(); const cursorOffset = { top: top - divOffset.top, left: left - divOffset.left }; console.log('光标位置:', cursorOffset); } } } </script> ``` 在上述示例中,当鼠标在`div`元素上抬起时,会触发`handleMouseUp`方法。该方法获取当前光标位置的`Range`对象,并计算光标相对于`div`元素的偏移量。最后,将光标位置输出到控制台。 请注意,上述示例仅适用于在鼠标抬起时获取光标位置。如果需要实时追踪光标位置的变化,可能需要在其他事件(如键盘事件、鼠标移动事件)中监听并更新光标位置。另外,还需要考虑光标在不同元素之间移动时的情况。 如果需要在特定的时机获取光标位置,可以根据具体需求调整事件和方法的绑定方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值