我用Angular 16为我为响应式设计创建的一个新的CSS实用程序构建了一个文档网站。为了演示响应式功能,我创建了一个具有可调整大小的组件
<iframe>
我将演示组件嵌入其中。我这样做是为了利用
<iframe>
的独立DOM实例,因此演示会响应
<iframe>
而不必调整整个浏览器窗口的大小,这对用户来说很方便。
我有两个样式表需要使用,一个用于CSS实用程序,另一个用于所有颜色定义。我唯一能让它们工作的方法就是把它们导入主
styles.css
我的角项目,并将其附加到头部
<iframe>
.
我的组件的代码看起来像这样,减去了一些与问题无关的东西。
@Component({
selector : 'responsive-window',
standalone : true,
imports : [ CommonModule ],
templateUrl : './responsive-window.component.html',
styleUrls : ['./responsive-window.component.css'],
changeDetection : ChangeDetectionStrategy.OnPush
})
export class ResponsiveWindowComponent implements OnInit, AfterViewInit, AfterContentChecked, OnDestroy {
/* I pass the components I want to embed through this Input */
@Input() Demonstration! : Type<Component>;
/* I use this to target the iframe in the template */
@ViewChild('domFrame', {static: true, read: ElementRef}) DomFrame! : ElementRef;
constructor(
private cdr : ChangeDetectorRef,
private vcRef : ViewContainerRef,
private zone : NgZone
){}
ngAfterViewInit(): void {
/* embeds the component into the iframe after the view is loaded */
this.embedContent();
}
public embedContent(): void{
/* targets the iframe */
const frame = this.DomFrame?.nativeElement.contentDocument || this.DomFrame?.nativeElement.contentWindow;
/* resolves the component */
const item : ComponentRef<any> = this.vcRef.createComponent<Component>(this.Demonstration);
/* for setting up a broadcast channel to send data back and forth from outside the iframe */
if(reflectComponentType(this.Demonstration)?.inputs.find(a=> a.propName === 'BroadcastName') !== undefined){
item.instance.BroadcastName = this.BroadcastName;
item.instance.ChannelName = this.ChannelName;
item.instance.TargetName = this.TargetName;
}
/* for the default styling of the iframe's body element */
const defaultStyles = document.createElement('style');
/* for attaching the main stylesheet of the angular app */
const stylesLink = document.createElement('link');
defaultStyles.innerText = `*{ padding : 0; margin : 0; box-sizing: border-box; overflow: hidden; } body{ display : grid; place-items: center; min-height: 0px; max-height: 100vh; grid-template-columns: 1fr; grid-template-rows: 1fr; background-color: hsl(var(--gray-100), 1); }`;
stylesLink.rel = 'stylesheet';
stylesLink.type = 'text/css';
stylesLink.href = 'styles.css';
/* embedding everything into the iframe */
frame.head.appendChild(defaultStyles);
frame.head.appendChild(stylesLink);
frame.body.appendChild(item.location.nativeElement);
}
}
至于我传递到这个组件中要嵌入的组件
<iframe>
,这是一个如何设置它们的示例。
@Component({
selector : 'app-example',
standalone : true,
imports : [CommonModule],
templateUrl : './example.component.html',
styleUrls : [ './example.component.css' ],
encapsulation : ViewEncapsulation.ShadowDom
})
export class ExampleComponent {
}
我必须将封装设置为
ShadowDom
否则,组件的任何样式都不会生效,也不会从中读取任何样式
样式.css
文件嵌入到
<head>
.跑步时
ng serve
一切都很完美,但当我跑步时
ng-build
并将文件加载到我的
c-panel
然后去网站,没有任何来自
样式.css
文件对嵌入到中的组件生效
<iframe>
.
我在嵌入式组件的样式表中更改了一些样式,只是为了看看它们是否会生效,它们确实生效了,这意味着它可以识别组件样式表中的样式,但当查看来自我的样式表的一些定义,包括所有颜色和CSS实用程序(它们都是CSS变量)时,它们都没有被定义。
我试图将这些样式表导入到组件的样式表中,但没有成功。然后我尝试将它们导入元数据中,如下所示。
@Component({
selector: 'app-product',
standalone: true,
imports: [CommonModule],
templateUrl: './product.component.html',
styleUrls: [
'../../../../assets/utility-styles.css',
'../../../../assets/color-defs.css',
'./product.component.css'
],
encapsulation: ViewEncapsulation.ShadowDom
})
我确保在copmonent的样式表之前先导入其他样式表,这样所有的值都会在使用之前定义好。我跑了
ng build
再次将文件加载到我的
c面板
但这也不起作用。我还将这些额外的样式表添加到
styles
数组在我的
angular.json
文件,看看这是否允许我将它们导入嵌入式组件,但也无法正常工作。
在the
responsive-window
您会注意到,我的代码中有一部分引用了
BroadcastName
,
ChannelName
和
TargetName
输入,用于设置广播频道,以便用户可以尝试不同的设置,这些设置将从外部的仪表板更改嵌入式组件中某些CSS属性的值
<iframe>
。我还不知道这是否也有影响,但我很担心。有人知道我该怎么解决这个问题吗?