WEB 编程:富文本编辑器 Quill 配合 Pico.css 样式被影响的问题
缘起
前端页面的美化,我采用 Pico.css,可以非常简单就把页面做得很漂亮。
富文本编辑器选用 Quill 也是非常简单就有了一个功能强大的富文本编辑器,尤其是完全不用考虑图文混排时的图片上传问题。
问题
但这两个玩意放到一个页面里面,Quill editor 的 Toolbar 上面的一部分按钮的样式,被 Pico.css 影响了,因为只是一部分样式被影响,而不是全部样式,因此整个画面变得很不协调。
解决方案
花了好多小时,和 Chat GPT 讨论了几轮,网络搜索各种和 CSS 有关的技术文章,发现最终都很难解决问题。
CSS 的问题
Quill editor 的页面元素,一个元素有多个 class 名称,也有 role="button" 这样的属性名称。导致它的样式受到 Quill editor 的 CSS 的影响的同时,一部分样式受到 Pico.css 的影响。
CSS 的语法,优先级,等等问题,很难处理这样的部分受影响。如果我在页面里面对 Editor 加上一个包装<div class="MyEditor"> Editor </div> 然后针对这个 MyEditor 单独定义一个样式,倒是可以因为这个定义的优先级,压制到 Pico.css 在这里的影响。但是在这里,我就得把 Quill editor 的 CSS 文件里面的内容都抄过来 -- 没有引用那个文件的方法。作为习惯了任何资源都可以用指针引用过来的程序员,发现CSS 这个语言是很傻逼的语言,连代码重用都做不到。代码的封装,代码的作用域这些,它完全处理不了。
使用 iframe 来解决封装的问题
最终,我决定把 Quill editor 放到一个单独的页面里面,这个页面不使用 Pico.css,把这个页面作为使用 Pico.css 的框架页面里面的一个 iframe 来加载。这样算是封装了,确实也不受 Pico.css 的影响了。
跳出 iframe 的问题
当用户在 Editor 里面编辑文章,提交后,如果服务器直接返回内容,则内容仍然在当前页面的 iframe 里面。如果想整个页面都跳转到新的页面 -- 比如跳到文章列表页面,后端可以直接向浏览器发送跳转的 JavaSctipt 的代码,这个代码当然也是 iframe 里面的页面在执行,这个代码让它的上一级窗口执行跳转,就跳出了 iframe 了。
使用 Delphi WebBroker 来做后端服务器程序的话,代码如下:
procedure TWebModule1.WebModule1WebActionItemContentUpdateAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse;var Handled: Boolean);
varS: string;
begin//接收来自 Quill Editor 的编辑文本S := Request.ContentFields.Values['html'];var SL := TStringList.Create;trySL.Text := S;SL.SaveToFile('test.txt');//发送 JS 到客户端,让它的父窗口跳转 -- 编辑器在 iframe 子窗口里面。这样就跳出 iframe 了!Response.Content := '<script language="javascript">window.top.location="/docshow";</script>';finallySL.Free;end;
end;//前端提交的路径指向这个事件方法的 Path 属性,因此服务器端收到前端的提交,会触发这个事件。
//在这个事件里面,我把用户在页面的编辑器里面输入的字符串,保存到文件里面。
//然后,让前端跳转到 /docshow 这个路径。浏览器页面会访问这个路径。
//我的测试程序在这个路径对应的事件方法,直接加载保存的文件内容输出给页面。
//这样的结果就是用户在编辑器里面输入完内容,点击提交,然后看到页面刷新,显示刚才提交的内容。
上述代码里面,关键是这一句:
Response.Content := '<script language="javascript">window.top.location="/docshow";
这里的 Windows.Top.Location 使得页面的 iframe 里面的页面调用最顶层窗口去访问一个新的路径,完成跳出 iframe 访问新路径的动作。
这里有意思的事情是:服务器端向浏览器输出一个 JavaScript 然后浏览器执行了。
结论
与其浪费时间折腾 CSS 这种傻逼语法,不如干脆绕开它,更省事。