简体   繁体   English

将样式传递给组件的最佳方式

[英]Best way to pass styling to a component

So I have this component called InputEdit (basically a Label that can be edited when you click on it... simple enough) and this component has its own shadowed DOM CSS styling.所以我有一个叫做InputEdit组件(基本上是一个可以在你点击它时编辑的Label ......足够简单)并且这个组件有它自己的阴影 DOM CSS 样式。 But of course each hosting component will want to set its own font size and color for the input component...但是当然每个托管组件都希望为输入组件设置自己的字体大小和颜色......

So what would be the best way?那么最好的方法是什么? Can you just pass in a styling class and apply the entire CSS to the component?你可以只传入一个样式类并将整个 CSS 应用到组件上吗? Or would it be better to pass each value manually as in:或者最好手动传递每个值,如:

     <InputEdit [color]="'red'"/>

Which would seem a lot of work, but again since we are using the shadow or emulated DOM, we can't just control the CSS externally.这看起来工作量很大,但同样,由于我们使用的是影子或模拟 DOM,我们不能仅从外部控制 CSS。

I am also aware that you can splice open the shadow and target direct elements via:我也知道您可以通过以下方式拼接打开阴影和目标直接元素:

/* styles.css */
UserInfo /deep/ InputEdit label {
    color: red;
    font-size: 1.1em;
}

Which will basically allow you to enter into a custom component named UserInfo / deep (any level ) / custom component InputEdit and target label with color red...这将基本上允许您输入名为 UserInfo / deep (任何级别) / 自定义组件 InputEdit 的自定义组件和带有红色的目标标签...

But again, I am wondering what is the best approach specifically for ng2 like passing a class config into a directive maybe?但同样,我想知道什么是专门针对 ng2 的最佳方法,例如将类配置传递给指令?

I would just use a styles input property on InputEdit, and pass in an object with the desired styles:我只会在 InputEdit 上使用一个styles输入属性,并传入一个具有所需样式的对象:

<InputEdit [styles]="stylesObj">                 // in host component's template

stylesObj = {font-size: '1.1em', color: 'red'};  // in host component class

<input [ngStyle]="stylesObj" ...>                // in InputEdit component's template

If you have multiple DOM elements you want to style, pass in a more complex object:如果您有多个要设置样式的 DOM 元素,请传入一个更复杂的对象:

<InputEdit [styles]="stylesObj">

stylesObj = {
  input: {font-size: '1.1em', color: 'red'}
  label: { ... } 
};

<label [ngStyle]="styles.label" ...>
<input [ngStyle]="styles.input" ...>

Mark Rajcok's answer is good for a group of styles, but if you're only going to allow the font-size and color to be changed, you may want to use a more direct approach like you started with (in this example, also enforcing only pixels instead of a more flexible string for demonstration purposes): Mark Rajcok 的回答适用于一组样式,但如果您只允许更改字体大小和颜色,您可能希望使用更直接的方法,就像您开始时一样(在本例中,也强制执行仅用于演示目的的像素而不是更灵活的字符串):

For Individual Style Properties :对于单个样式属性

Component:成分:
<InputEdit [color]="'red'" [fontSize]="16">

component.ts:组件.ts:
Input() color: string = 'black';
Input() fontSize: number = 18;

component.template:组件模板:
<input type="text" [style.color]="color" [style.fontSize.px]="fontSize">


If Allowing a Group of Styles :如果允许一组样式

Component:成分:
<InputEdit [styles]="{backgroundColor: 'blue', 'font-size': '16px'}"> NOTE: Make sure the CSS properties are camelCased or in a string if there is more than one word. <InputEdit [styles]="{backgroundColor: 'blue', 'font-size': '16px'}">注意:如果有多个单词,请确保 CSS 属性是驼峰式字符串。

component.ts:组件.ts:
@Input() styles: any = {};

component.template:组件模板:
<input type="text" [ngStyle]="styles">

update更新

::slotted is now supported by all new browsers and can be used with `ViewEncapsulation.ShadowDom ::slotted现在被所有新浏览器支持,并且可以与`ViewEncapsulation.ShadowDom 一起使用

https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted

original原来的

/deep/ , ::shadow and >>> are deprecated. /deep/ , ::shadow>>>已弃用。 ::ng-deep is the best option until all browsers properly support style encapsulation and ViewEncapsulation.Emulated can be removed. ::ng-deep是最好的选择,直到所有浏览器都正确支持样式封装并且可以删除ViewEncapsulation.Emulated

The deprecation is only for the native implementation in Chrome (other browsers never implemented it) but Angular has its own emulation of these CSS combinators in ViewEncapsulation.Emulated (default)弃用仅适用于 Chrome 中的本机实现(其他浏览器从未实现过),但 Angular 在ViewEncapsulation.Emulated (默认)中有自己对这些 CSS 组合器的模拟

/deep/ , ::shadow and >>> ::ng-deep can therefore be used just fine in Angular2. /deep/ , ::shadow>>> ::ng-deep因此可以在 Angular2 中很好地使用。

For more than simple classes or style property settings use ngStyle Angular 2.0 and ng-style对于不仅仅是简单的类或样式属性设置,请使用ngStyle Angular 2.0 和 ng-style

If you want to leave it up to the component to define the actual css you can try one of the following:如果您想让组件来定义实际的 css,您可以尝试以下方法之一:

Add a property on your component for each 'logical' style setting, for instance headerSize .在您的组件上为每个“逻辑”样式设置添加一个属性,例如headerSize

@Input('headerSize') headerSize: ('small' | 'large');

Then your component can check its value in one of a few ways to style itself:然后您的组件可以通过以下几种方式之一检查其值来设置自身的样式:

  1. Modify the HTML itself by showing or hiding child elements通过显示或隐藏子元素来修改 HTML 本身

    <h1 *ngIf="headerSize == 'large'">{{ title }}</h1> <h2 *ngIf="headerSize == 'small'">{{ title }}</h2>
  2. Set a custom class dynamically inside the component somewhere, and style it:在组件内的某处动态设置自定义类,并为其设置样式:

     <div [ngClass]="'header-' + headerSize"> .header-small { h1 { font-size: 20px; } } .header-large { h1 { font-size: 30px; } }
  3. Set a custom class dynamically at the class level.在类级别动态设置自定义类。 This is the same as #2 and doesn't require a wrapper element.这与#2 相同,不需要包装器元素。 However it's less than trivial to actually enable and disable these classes.然而,它的不到琐碎实际启用和禁用这些类。

     @HostBinding('class.header-small') _header_small; @HostBinding('class.header-large') _header_large;

Also note that if you're using ng-content that the styles applied are the styles defined in the containing component and not the component that actually does the content replacement.另请注意,如果您使用ng-content ,则应用的样式是包含组件中定义的样式,而不是实际执行内容替换的组件。

Another option is use CSS variables.另一种选择是使用 CSS 变量。 In this case, to style the color and font-size of the child component's label, you could set two variables on the parent component's CSS and make use of them in the child's CSS.在这种情况下,要设置子组件标签的颜色和字体大小的样式,您可以在父组件的 CSS 上设置两个变量,并在子组件的 CSS 中使用它们。

userInfo.component.css用户信息.component.css

InputEdit {
  --label-color: red;
  --label-font-size: 1.1em;
}

inputEdit.component.css inputEdit.component.css

label {
  color: var(--label-color, #000);
  font-size: var(--label-font-size, 1em);
}

Of course, this means you have to define every property you want to be styled, but if you only need to set a few styles on the child, it works fine.当然,这意味着您必须定义要设置样式的每个属性,但是如果您只需要在子项上设置几个样式,它就可以正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM