react写法
<div id="contentTable" className={styles['infoBox']} placeholder='请输入内容' contentEditable suppressContentEditableWarning onblur={this.blurDiv} />
注意⚠️
contentEditable
and contains children
managed by React.如果我们想给我div加一个placeholder的话,如下:
.infoBox {
width: 100%;
height: 115px;
padding: 16px;
line-height: 1;
outline: none;
&:empty::before {
content: attr(placeholder);
color: #808080;
}
}
// 光标从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)
}