WEB 编程:富文本编辑器 Quill 配合 Pico.css 样式被影响的问题之Shadow DOM

embedded/2024/10/16 2:05:28/

前情提要

前面我写过一篇文章讲这个事情。用的是 iframe 的方法。文章链接:

WEB 编程:富文本编辑器 Quill 配合 Pico.css 样式被影响的问题-CSDN博客

问题来了

使用 iframe 确实可以在框架页面有 Pico.css 的情况下,在 iframe 里面的 Quill Editor 不受影响。但是,编辑器里面用户输入的内容,是需要提交到服务器端的。因此,编辑器是嵌套在一个 <form> <div id="MyEditor"></form> 里面的。同时这个 Form 里面还要有一个提交按钮。

如果仅仅是提交编辑器里面的内容,那这样做就没有问题。但是,可能还有单独的文章表,等等其它需要用户输入的东西,要一起提交。比如文章标题:<input type="text" id="MySubject">, 而这个输入框是需要被 Pico.css 给予样式的。如果把这些输入框和 Editor 一起放进 iframe 里面,则无法接受 Pico.css 的样式!

采用 Shadow DOM 来解决这个问题

Shoadow DOM 的基本概念

页面上很多元素,输入框,按钮,等等,构成页面的 DOM。

页面上还可以有 Shadow DOM,挂载在 DOM 的某个节点底下。在 Shadow DOM 里面的页面元素比如一个<input type="text"> 或者一个按钮比如 <button> 也是正常显示在页面上的,但是,这些元素不受页面上的 CSS 的影响。相当于屏蔽掉了页面上的 CSS;

具体操作

思路

我们是把 Editor 放到 <div id="MyEditor"></div> 里面的。我们把这个部分,放进 Shadow DOM;

然后在页面,也就是 Shadow DOM 外面,有一个表单,表单内部有提交按钮,以及文章标题输入框。那么,这些,当提交按钮被点击,就可以提交表单内容。

问题

如果把表单(<form>)放到 Shadow DOM 外面,那么,提交按钮如何获取到在 Shadow DOM 里面的 MyEditor 的用户输入的内容?

如果把一个页面元素比如 quill Editor 放进 Shadow DOM

首先,把 quill Editor 相关的 HTML 代码,放进 HTML 模板。这个模板的内容加载到浏览器里面后,浏览器是不会显示的。模板的代码如下:

<template id="my-element"><!-- 用 template 来封装这个编辑器,避免它被页面上的其它 CSS 污染 --><!-- quill 编辑器的封装 https://quilljs.com/ --><script src="https://cdn.jsdelivr.net/npm/quill@2.0.2/dist/quill.js"></script><link href="https://cdn.jsdelivr.net/npm/quill@2.0.2/dist/quill.snow.css"rel="stylesheet"><style>.edit_container { font-family: 'Avenir', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;text-align: center; color: #2c3e50; margin-top: 60px; } .ql-editor{ height:400px;}</style><div id="editor1"><h2>这是编辑框里面的内容,服务器端加载内容可以直接填到这里。<#AContent>这里替换</h2></div><script>const MyContainer = host.shadowRoot.querySelector("#editor1");const quill = new Quill(MyContainer, {modules: {toolbar: [[{header: [1, 2, false]}], ['bold', 'italic', 'underline'], ['image', 'code-block'], ],},theme: 'snow'});</script>
</template>

其实就是用 <template > 这个标记来把一个 HTML 的网页元素包起来,就是一个模板了。

使用模板在页面里真正创建和显示这个元素

            <div id="MyHost"></div><script>const host = document.querySelector("#MyHost");const shadow = host.attachShadow({mode: "open"});const template = document.getElementById("my-element");shadow.appendChild(template.content);</script>

首先定义一个容器,MyHost 然后用代码,把模板里面的 HTML 代码描述的 HTML 元件挂在这个 MyHost 的底下,作为它的 Shadow DOM。如果页面显示正常,打开浏览器的开发者工具,查看页面元素,会看到开发者工具里面,在 MyHost 那个 DIV 底下,会显示【shadow-root】的字样,再底下才是这个 Editor 的代码。

解决提交的问题

表单(<form>)和提交按钮,放在页面里面,而不是 Shadow DOM 里面。这样按钮才能获得 PICO.CSS 提供的样式。同样需要提交的文章的标题栏,也在这个表单里面,也能够获得样式。

但是,Editor 不在这个表单里面。如果把表单和 Editor 放在一起,那就必须把标题输入框和按钮也和 Editor 放一起,那这两个玩意就无法获得页面上的 PICO.CSS 提供的样式了。

因此,我要用 JavaScript 代码,从 Shadow DOM 里面的 Editor 获得用户输入的数据,然后给外面的表单提交。代码如下:

       <form id="myForm" action="ContentUpdate" method="post"><input type="hidden" name="delta" id="deltaInput"><input type="hidden" name="html" id="htmlInput"><input type="text" name="MySubject1" id="MySubject1" value="我的标题"><input type="submit" value="提交"></form><script>const host = document.querySelector("#MyHost");const shadow = host.attachShadow({mode: "open"});const template = document.getElementById("my-element");//把页面模板放到容器的 Shadow DOM 里面去。shadow.appendChild(template.content);//监听提交按钮,把提交内容复制到隐藏字段里面再提交,服务器读隐藏字段值const MyEditor = host.shadowRoot.querySelector('#editor1');//if not MyEditor alert("没找到编辑");//const quill = host.quillInstance;document.getElementById('myForm').addEventListener('submit',function() {// 获取 Quill 编辑器的内容const delta = JSON.stringify(quill.getContents());const html = quill.root.innerHTML;//delta = '';//html = MyEditor.outerHTML;// 将内容放入隐藏输入框中document.getElementById('deltaInput').value = delta;document.getElementById('htmlInput').value = html;});</script>

注意,上述代码里面的 quill 是在 Editor 的模板文件里面声明和创建实例的。这里仅仅是调用它。

煞科

到这里,整个页面就做好了。实现了:

  1. 代码封装;把 Editor 单独放到一个文件里面,加上 Template 套起来。
  2. CSS 隔离:把 Editor 放到 Shadow DOM 里面,防止被页面的 CSS 污染。
  3. 提交:用 JavaScript 把用户在 Editor 里面输入的内容提取出来,放到一个表单内部的隐藏字段里面,就可以正确提交了。一个在 Shadow DOM 里面创建的 Editor 对象,只要创建时对象是一个 JavaScript 的全局变量,在其它地方也是可以调用到的。

吐个槽

前端代码的语法真是狗屎。像 CSS 这种完全没有作用域和封装的概念,需要用 Shadow DOM 或者 iframe 之类的技巧来避开语法的坑,完全属于奇巧淫技的做法,属于野路子,非正常写代码的路子。真是可怜成天专门写前端代码的童子。

各位,看完本文如果觉得有点干货内容,点个赞吧。


http://www.ppmy.cn/embedded/118675.html

相关文章

7款国内AI搜索引擎大全网站

与传统搜索引擎相比&#xff0c;AI搜索引擎利用先进的自然语言处理、机器学习和深度学习技术&#xff0c;提供更加精准和个性化的搜索服务。小编就来和大家分享国内免费的AI搜索引擎网站&#xff0c;方便大家体验使用。 AI搜索引擎网站大全&#xff1a;https://www.bgrdh.com/f…

uniapp APP自动更新组件

在uniapp中实现APP自动更新功能&#xff0c;主要涉及到客户端在功能不断迭代过程中&#xff0c;需要进行自动更新。uniapp一个详细的实现步骤&#xff0c;包括客户端和服务器端的配置&#xff1a; 服务器端配置 版本信息管理 服务器端需要维护一个数据库或配置文件&#xff…

Python编码系列—Python观察者模式:实现事件驱动架构的利器

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

001、restful设计规范

https://www.kancloud.cn/kancloud/rest-api-design-safety/78113 https://www.kancloud.cn/kancloud/http-api-design/78123 https://www.kancloud.cn/kancloud/http-api-guide/56268 restful接口设计规范 按照restful接口设计规范 GET &#xff08;SELECT&#xff09;&…

安装软件及apt install -f修复均报错

UOS统信安装软件过程及修复依赖过程&#xff0c;可排查deepin-installer和dpkg问题 文章目录 一、问题现象二、问题原因三、解决方案 一、问题现象 执行apt install -f 都会出现该报错&#xff0c;如图所示&#xff1a; 二、问题原因 造成这种情况的原因在于/var/lib/dpkg/…

Spring JDBC及声明式事务

目录 Spring JDBC基础概念 Spring声明式事务 事务传播方式 Spring JDBC基础概念 Spring JDBC 封装了原生的JDBC API&#xff0c;使得处理关系型数据库更加简单。Spring JDBC的核心是JdbcTemplate&#xff0c;里面封装了大量数据库CRUD的操作。使用Spring JDBC…

自己开发一个网站系列之-从基础到高级

自己开发一个网站系列之-从基础到高级 在上一篇博客中&#xff0c;我们介绍了网页开发的基础知识&#xff0c;包括HTML、CSS和JavaScript的基本用法。这是一个很好的起点&#xff0c;但如果你想进一步提升自己的技能&#xff0c;掌握更多高级概念和技术&#xff0c;就必须深入…

【CSS】字体文本

color 颜色font-size 大小font-family 字体font-style 样式font-weight 加粗text-decoration 下划线text-shadow 阴影text-transform 大小写变换text-indent 缩进text-align 水平对齐 、vertical-align垂直对齐text-overflow 溢出word-wrap 换行word-break 截断white-space 空白…