内容比较多,好好看看,收获匪浅
前言:有这么一个场景,比如一个dom元素是可以编辑的,并且编辑样式得自己写一下,这时候我们考虑单独写一套div来控制编辑样式和编辑的内容。内部有很多的span节点需要渲染,对这些span里面的文本需要修改调整,调整完对应文本传给后台做更新,那么这个流程应该怎么做?接下来我们梳理一下做法
咱们分两种情况来讲:
第一种是简单场景,只编辑一个div里面的文本内容,比较简单。
第二种是复杂场景,编辑div下很多个span里面的元素内容
一、第一种场景,只编辑一个div里面的文本内容做交互
对这个div里面的内容做编辑,因为必须用公司里的UI出的样式来做,所以咱们就单独写一个
原始dom元素:
点击修改,调整之后的dom元素:
可以明显看到,dom自己写了一套样式,同时在可编辑的div元素上增加了一个属性contenteditable="true"表示这个div元素可以编辑
同时在当前可编辑的dom元素上,可以增加一些方法,比如onBlur,onFocus,onChange等等方法,方便做其他业务逻辑处理
我在这里增加了一个onBlur={onContentChange}方法
记录了一下修改之后的最新内容,在dom里可以直接渲染出来,也可以直接走接口刷页面
最后点击完成编辑按钮,和后台交互就行了
二、第二种复杂场景,编辑div下很多个span里面的元素内容
先看后台返回的数据格式和展示的样式
挑了第三条的数据咱们看一看怎么处理
数据:渲染:
他是这么渲染的
现在要求是,点击编辑,编辑这一整块儿内容,然后把数据组装成每一个Words的item传给后台,该怎么处理?
处理方案:
因为是整个div元素编辑,所以给外层div增加contenteditable="true"可编辑属性,样式自定义,如下
可以编辑了之后,怎么对应编辑的每一个span和后台数据怎么组装呢?这样搞一下
首先我们给每一个span上把当前元素对应的数据设置成属性,放到dom元素上
然后我们定义一个ref属性,给可编辑div起个名
<div className="flex flex-col m_input" contenteditable="true" ref={allTextRef} >xxxxx</div>
然后点击完成编辑按钮,执行逻辑
if (allTextRef.current) {
const spans = allTextRef.current?.querySelectorAll('span');
const newData = Array.from(spans).map((span: any) => ({
Id: span.dataset.id,
SentenceId: span.dataset.sentenceId,
Start: span.dataset.start,
End: span.dataset.end,
Text: span.textContent,
}));
console.log("组装数据:", newData);
}
下面就是我们组装好的数据了,按照字段传给后台,刷新咱们页面就OK了