现在的需求是这样的。想做一个英文文章阅读的网站,文章当中的每一句话都可以点击句末的上标翻译,然后句子的下面就显示中文。当然还可以点击句末的修改按钮修改这句话。
现在遇到一个问题,就是文章可以由段落或列表组成, 一个段落(p)中可能会有多个句子(span),我现在想的是将文章的所有句子都存放在表中,根据不同的类型来判断这个句子在渲染成 html 时,应该使用哪些标签。
例如句子的类型可以是
<p><span>内容</span>
<span>内容</span></p>
<ul><li><span>内容</span>
<span>内容</span></li></ul>
b 就是 begin ,e 就是 end
现在数据库中的 sql 是这样的
create table en_article_sentence
(
id bigint unsigned auto_increment
primary key,
article_id bigint not null,
type varchar(64) not null,
en text null,
zh text null,
audio varchar(64) null,
created_at datetime default CURRENT_TIMESTAMP null,
updated_at datetime default CURRENT_TIMESTAMP null
);
前台使用的是 react ,react 语法使用的是 JSX ,JSX 在使用 html 标签时,必须成对出现,所以在渲染时就不好处理了。
如果我使用 <div dangerouslySetInnerHTML={{__html: sentence}}></div>
这种方式来渲染 html , 那么就不能调用函数组件中的方法,进行修改。 如果直接根据type
类型来判断,html 标签又必须成对出现。
这篇帖子描述了 现在的困境 https://www.v2ex.com/t/936765
有 v 友说这样设计不太好,所以想要请教一下,要如何设计才能比较好的实现我上述的需求呢?
1
pelloz 2023-05-02 13:09:23 +08:00
存两张表。
第一张表存完整的文章富文本格式,可以直接提供给前端渲染,并且每个需要翻译的句子的 span 标签有唯一的 id ,比如<span id="1-1">hello<span> 第二章表存文章 id 和句子 id 和对应的翻译。 |
2
NoOneNoBody 2023-05-02 13:12:08 +08:00
不熟前端,只会少量 GUI 的工作,html 扔下太久了,只懂爬虫相关的部分
第一眼,这个表至少缺一个标明顺序的字段,虽然 id 也是有序的,但应该有一个较明确标明该 id 相对 article_id 的顺序的标识,单靠 id 排序不保险;如果想在中间插入一句,没有相对顺序,你这个 article 就要重排了 工作上是单句,但读取数据是否也是单句?如果确定“必然”是每次读取都是整篇文章,那未必需要每句作为 record ,只要整篇读取后可以顺利拆分每句就足够了;但如果确实有只读取某一句这种场合,就照这样吧,附加问题是累积数据量庞大时要考虑 IO 前面说的“顺利拆分”,其实方法很多,例如可以在入库时,按粒度添加一些特殊分隔符,读取后 split 也很容易 至于前端渲染的问题,个人觉得不应因为考虑前端而改变数据结构,只要能正确拆分粒度,后面就交给前端考虑了 这样的话,即使前端换了一套技术,也不影响。如果“为了前端方便处理”而写死数据结构,遇到换前端、前端 BUG 怎么办?整个数据库重构么? 前端问题 “……就不能调用函数组件中的方法”,不清楚这个函数究竟是写得多么死,但即使这样,也能加个闭包预处理格式吧? 类型那些最好不要从 html 语法判断,应该多利用 selector ,如 css selector 或者 dom/xpath 等等,html 只是堆砌元素,应该用 selector 提取,例如<p><span>写成<p><span class='pb-span'>或者<p><span id='pb-span-1'>,这样就容易了 |
3
TomVista 2023-05-02 14:02:36 +08:00
存个扁平树吧,取出来,再组织起来,然后渲染
{ id:'1' name:'小猪佩奇', paragraph:[{ sentence:[{ text:'天气晴朗,' zh:'', en:'', },{ text:'猪爸爸和猪妈妈出去打工了.' zh:'', en:'', }] }] }, `select * from sentence where articleid = 1` let article = sentence.forEacht(item=>{paragraph[item.paragraph].push(item.text)}) |
4
kongkx 2023-05-02 21:29:30 +08:00 via iPhone 2
可以借鉴一些 editor 的 doc 数据结构的设计,比如 draftjs 的扁平化 ,slatejs 的 nested ,或者 portable text
https://docs.slatejs.org/v/v0.47/guides/data-model 既然用 react 了,不一定需要组装成 html 再渲染。直接维护组件树就行,组件上还能继续做功能。 |