通过 innerHTML 输入时 span 不应用 css 样式

Posted

技术标签:

【中文标题】通过 innerHTML 输入时 span 不应用 css 样式【英文标题】:span doesn't apply css style when entered via innerHTML 【发布时间】:2019-03-28 22:02:36 【问题描述】:

我有 Angular 应用程序,作为其中的一部分,我在 div 中显示查询结果(具有 JSONContainer 的 ID)。

我想突出显示结果中的特定查询,所以我使用了一个管道来搜索结果,并将文本中的 FIELD:VALUE 替换为:

<span class="highlightSpan">FIELD:VALUE</span>.

我在组件中添加了以下css:

div#JSONContainer span.highlightSpan
    background-color: rgba(28, 243, 28, 0.5) !important;
    color:red !important;
    padding: 1px;
    margin:1px;

我也尝试在 .highlightSpan 下添加相同的样式,结果相同。

我使用存储整个 JSON 的“数据”变量和存储查询的“查询”变量通过 innerhtml 在包含组件中插入这个跨度和其余文本:

    <div class="col-xs-12" id="JSONContainer"
        [innerHTML]="data | textHighlight:query">
    </div>

(我没有使用字符串插值,因为数据 var 是 json 形状的,我使用 html 代码设置样式,如 html br 标签,而字符串插值仅显示文本)。

当我将鼠标指向谷歌开发工具中的相关跨度时,我看到创建了类的跨度:

但是没有应用 css 样式,它甚至没有显示在谷歌开发工具中:

编辑:我知道它不显示(我从 img 中删除了它),但跨度位于 div#JSONContainr 中,如所述。

编辑 2: 这是相关的树:

为什么会这样?

如何使css样式生效?

谢谢!

【问题讨论】:

该跨度实际上是否位于最终 DOM 内的 div#JSONContainer 内?我们无法从您的屏幕截图中看出这一点,只是直接父级有所不同。 您能提供生成的示例 HTML 吗? 看起来您的 span 不在 div#JSONContainer 内,或者您有多个 #JSONContainer(重复 id) 你的 id #JSONContainer 在哪里? 大家好,出于隐私原因,我从 google dev 屏幕截图中删除了 html 树,但如上所述,span 位于 jsonContainer 中。另外,我认为任何其他样式都不适用,因为谷歌开发人员不会显示高亮样式被否决,它根本不会显示它们@Justinas。 【参考方案1】:

发生这种情况是因为您正在动态添加span 元素并且它不是您的组件的一部分,因此span 元素没有使用组件样式隔离进行装饰。当您探索呈现为 html 的组件时,您会看到每个元素都具有类似 _ngcontent-c2 的属性,但您的 span 没有,因此它不是该组件样式的一部分。

您可以将您的 css 更改为:

::ng-deep div#JSONContainer span.highlightSpan

为组件的后代设置样式(动态添加的其他组件或元素)。或者,您可以将样式添加到全局样式中,使其不属于该组件隔离的一部分。

我创建了stackblitz demo 来模拟你的情况。

你可以阅读更多关于angular view encapsulation的信息。

【讨论】:

试试::ng-deep div#JSONContainer .span.highlightSpan 我试过了,还是不行。我不明白为什么这种风格甚至没有出现在谷歌开发工具中。 更新了演示以更贴近您的情况。你使用的是什么版本的角度?当::ng-deep 不适合您时,将样式移至全局styles.css 我使用 Angular 6。添加到全局 css 是什么意思?用什么语法? :: ng 终于完成了深入的工作,只需要修复错字并删除“span”之前的点。谢谢!【参考方案2】:

在您的 PIPE 中,您必须导入

import  DomSanitizer, SafeHtml  from '@angular/platform-browser';

添加到构造函数

  constructor(private sanitizer: DomSanitizer) 
  

在变换函数中返回

this.sanitizer.bypassSecurityTrustHtml('YOUR HTML');

【讨论】:

嗨。我得到一个错误,告诉我 bypassSecurity 功能仅在有 如果你的 css 样式在组件中的其他原因,请尝试将其移动到全局 css 文件中。 上述注释(使用全局css文件,例如styles.scss)绝对是最好的解决方案。你不需要绕过 dom sanitizer,也不需要在组件装饰器中设置 encapsulation: ViewEncapsulation 为 None ,你仍然可以使用 [innerHtml|="article" 来渲染从你的 cms 接收到的 html。您可以在呈现的 html 周围添加 包装器以选择特定的 css。

以上是关于通过 innerHTML 输入时 span 不应用 css 样式的主要内容,如果未能解决你的问题,请参考以下文章

vue开发中使用span替代input输入,兼容IE

jQuery:在 .innerHTML 或 .text 更改时制作动画

使用 Angular 2+ [innerHTML] 添加包含样式属性的 html

7.操作div和span

原生js中的innerHTML的用法

从 span 的 innerHTML 获取`selectionStart`