【问题标题】:Style html,body from web component (Angular 2)样式 html,来自 Web 组件的正文(Angular 2)
【发布时间】:2016-04-25 04:45:53
【问题描述】:

我正在开发 Angular 2 中的 LoginComponent,它应该“重新设计”htmlbody 标记,因此我可以放入特定于登录页面的背景图像。

但在我的login.css 中添加html, body 的样式似乎不起作用。

有没有办法从组件中覆盖html, body 的样式?或任何与此相关的元素。

我尝试过类似的方法:

:host(.btn) { ... }
:host(.btn:host) { ... }
.btn:host { ... }

Login 组件外部的元素设置样式。但似乎没有任何效果。

【问题讨论】:

  • 这只是我个人的看法,但是你为什么不直接在body中添加一个登录类或者类似的东西,然后添加特定于该类的css样式覆盖常规样式,这感觉比覆盖每个组件内的样式更级联。

标签: angular shadow-dom


【解决方案1】:

将您的样式放入一个 css 类/类中,并在您的组件中执行以下操作:

constructor() {
    document.body.classList.add("mainMapPageBody");
  }

ngOnDestroy(){
    document.body.classList.remove("mainMapPageBody");
}

这使您不必在构造函数/析构函数中编写大量添加和删除样式,从而使调试更容易,就像在其他答案中一样。

【讨论】:

    【解决方案2】:

    作为附加更新,当使用 Angular: 9.1.12 时,可以使用 src/styles.css 文件来为 body 标签添加样式。这个假设 src/angular.json 项目的架构师对象的样式数组已设置为 src/styles.css

    配置全局样式表时,angular.json 文件应如下所示:src/styles.css。 Angular 文档中还有更多详细信息:https://angular.io/guide/workspace-config#style-script-config

    { 
        "projects": { 
            "app": { 
                "architect": { 
                    "styles": ["src/styles.css"] 
                } 
            } 
        } 
    }
    

    【讨论】:

      【解决方案3】:

      很简单试试这个?

      //Add Style
      document.body.style.overflow = 'hidden'
      
      // Remove style
      document.body.style.removeProperty('overflow')
      
      //Remove style on destroy
      ngOnDestroy(): void {
        document.body.style.removeProperty('overflow')
      }
      

      【讨论】:

      • 这解决了@Sasxa 回答中的全局溢出问题
      【解决方案4】:

      我在我的组件中使用这种方法,在路由器插座中加载:

            ngOnInit() {
              // Change <body> styling
              document.body.classList.add('align-content-between');
            }
      
            ngOnDestroy() {
              // Change <body> styling
              document.body.classList.remove('align-content-between');
            }
      

      【讨论】:

        【解决方案5】:

        我的使用方式是

        constructor() {
            document.body.className = "bg-gradient";
          }
        
        ngOnDestroy(){
            document.body.className="";
          }
        

        这将为特定组件的主体动态添加和删除样式。

        【讨论】:

        • 有时简单的解决方案是最好的;-)
        【解决方案6】:

        你可以试试

        body {
          /* body styles here */
        } 
        

        但是组件中的样式不应该应用于它们自身之外的元素。

        另一种方法是在主组件中使用body 作为选择器,并使用主机绑定设置/删除正文上的 CSS 类,以使添加到 index.html 的 CSS 匹配。

        @Component({
          selector: "body", 
          host: {
            "[class.some-class]":"someClass" 
          }, 
        }) 
        export class AppComponent {
          constructor(private loginService: LoginService) {
            loginService.isLoggedInChanged.subscribe((value) => {
              this.someClass = value;
            });
          }
          someClass: bool = false;
        } 
        

        当您将 someclass 设置为 true 时(对服务使用一些绑定,该类被添加到正文中。

        如果不想全局添加 CSS,也可以直接绑定到样式属性

        @Component({
          selector: "body", 
          host: {
            "[style.background-image]":"bodyBackgroundImage()" 
          }, 
        }) 
        export class AppComponent {
          bool isLoggedIn = false;
          constructor(private loginService: LoginService) {
            loginService.isLoggedInChanged.subscribe((value) => {
              this.isLoggedIn = value;
            });
          }
          function bodyBackgroundImage() {
            return this.isLoggedIn ? 'url("gradient_bg.png")': 'none';
          }
        } 
        

        更新

        DomAdapter 不见了。 Renderer2 应该提供类似的功能。

        罢工>

        直接从登录组件设置&lt;body&gt; 样式的方法是使用DomAdapter(另请参阅https://github.com/angular/angular/issues/4942

        System.import('angular2/src/platform/browser/browser_adapter').then(function(browser_adapter) {
          browser_adapter.BrowserDomAdapter.makeCurrent();
        })
        ...
        _dom: DomAdapter = new BrowserDomAdapter();
        _dom.setStyle(_dom.query('body'), 'padding', '50px');
        

        【讨论】:

        • 似乎不允许使用 body-selector(不再),引用自己的话 (stackoverflow.com/questions/41249161/…) 所以您在这里建议的第三种解决方案是唯一可能的解决方案?
        • thx 举个例子。不过我的 linter 告诉我,使用“body”选择器是不正确的(不管应用程序如何构建)。 codelyzer.com/rules/component-selector 指的是一些角度指南。嗯,我认为在这种情况下会出现 linter 错误。
        【解决方案7】:

        我对 margin-top 有同样的问题,我修复的方式是

        constructor(
            private _renderer: Renderer2,
        ) {
            this._renderer.removeStyle(document.body, 'margin-top');
        }
        

        这对我来说非常有效。

        【讨论】:

          【解决方案8】:

          我不确定这是否正是您正在寻找的,但这不会给您留下永久更改的身体背景图像。

          这是我为类似的事情所做的。如果您只想影响此页面的正文背景图像,这可能会起作用。 (我尚未对此进行全面测试,但它似乎适用于 Windows 浏览器。)

          在组件内部,您可以在构建组件时直接通过 DOM 工作。当它被破坏时,您可以撤消更改。

          export class SpecialBackground  {
            constructor(){
              document.body.style.backgroundImage = "url('path/to/your/image.jpg')";
              document.body.style.backgroundPosition = "center center";
              document.body.style.backgroundRepeat = "no-repeat";
              document.body.style.backgroundAttachment = "fixed";
              document.body.style.backgroundSize = "cover";
            }
            ngOnDestroy(){
              document.body.style.backgroundImage = "none";
            }
          }
          

          出于您的目的,当您单击按钮时,您可以使用不同的函数(而不是构造函数),您应该一切顺利。

          【讨论】:

            【解决方案9】:

            我刚刚编辑了 styles.scss 文件,它对我有用。

            【讨论】:

            • 但有条件?
            • @BenTaliadoros 请解释一下你所说的有条件是什么意思?样式条件通常写在 [ngClass] 或 [ngStyle] 中。但我感觉你在谈论别的东西。
            • 对不起,我的意思是你如何有条件地向正文添加样式,除非根组件包含正文标签,否则 [ngClass] 将无法在正文标签上工作
            • @BenTaliadoros 我想唯一可能的方法是使用 js,并将数据注入回 html/css。你能指定你想做什么吗?
            • 所以我有一个覆盖层,它在 body 元素上放置一个类,但我的 angular 应用程序是 body 内的引导程序。我稍微用js来瞄准身体,但感觉有点不棱角,希望有更好的方法
            【解决方案10】:

            最好在根级别添加 css 文件并在 angular-cli.json 中配置它或在 index.html 中添加它。这样您就可以编写您的重置和全局样式,而无需担心 shadow dom 和其他概念。

            【讨论】:

              【解决方案11】:

              您需要使用ViewEncapsulation 更改组件服务css 的方式。默认情况下它设置为Emulated 和角度将

              添加一个包含代理 id 的属性并预处理样式规则

              要更改此行为 import ViewEncapsulation from 'angular2/core' 并在组件的元数据中使用它:

              @Component({
                ...
                encapsulation: ViewEncapsulation.None,
                ...
              })
              

              【讨论】:

              • 这对我有用,并且是一种比标记为答案的方法更好的方法。谢谢。
              • 谢谢!这应该是公认的答案。
              • 如果我错了,请纠正我,但这不会允许更改每个组件的全局(正文选项卡)样式,不是吗?这只会将 css 添加到应用程序中,并且它会一直存在,即使加载了不同的组件。
              • @Sasxa,如果我们不想影响这些全局样式的子组件怎么办?
              • 这会更改所有组件的值。这根本不是原始请求者所要求的。 (他要求覆盖,而不是更改属性。)
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-05-09
              • 2016-10-02
              • 1970-01-01
              • 1970-01-01
              • 2017-03-06
              • 2017-09-22
              • 2017-10-30
              相关资源
              最近更新 更多