我正在学习Angular,有些东西我真的不明白。我的应用程序在所有浏览器(Chrome, Firefox, Brave, Opera,移动版本也)上运行良好,除了Safari(桌面和移动)。我的应用程序启动很好,除了我的脚本从资产文件夹。("src/assets"。
angular.json
...
"scripts": ["src/assets/js/layout.js"]
...
layout.js
'use strict';
var layoutInit = function layoutInit(){
const header = document.querySelector("header")// return null on safari;
const main = document.querySelector("main") // return null on safari;
const footer = document.querySelector("footer") // return null on safari;
function resize(){
main.style.minHeight = window.innerHeight - (footer?.offsetHeight ?? 0) + "px";
main.style.paddingTop = (header?.offsetHeight ?? 0) + "px";
}
window.onresize = resize;
resize();
}
if(document.readyState === 'loading' || document.readyState === 'interactive'){
document.addEventListener('DOMContentLoaded', layoutInit)
}else{
layoutInit()
}
Safari版本:15.6.1Angular: 15
有人遇到过这个问题吗?
首先:我不能回答这个问题。我的猜测是与Safari如何/何时加载脚本有关?
然而,我宁愿建议替代方案作为你目前拥有的更好的实践(除非你有一个特别好的理由?);有一个可爱的Angular SPA,它可以做你想做的一切,但然后使用一个外部脚本来设置页面布局,这是很奇怪的。
- 移动到应用程序
假设你有一个基本的app.component.html
,看起来像这样当前:
<div id="header">...</div>
<div id="main">
<router-outlet></router-outlet>
</div>
<div id="footer>...</div>
添加一些视图子使用:
<div id="header" #header>...</div>
<div id="main" #main>
<router-outlet></router-outlet>
</div>
<div id="footer" #footer>...</div>
所以它们可以在app.component.ts
中访问:
@ViewChild('header') public header: ElementRef;
@ViewChild('main') public main: ElementRef;
@ViewChild('footer') public footer: ElementRef;
然后在这里也处理你的大小调整:
@HostListener('window:resize'. []) public onResize() {
this.resizeLayout();
}
private resizeLayout(): void {
if (!this.main) return; // make sure it all exists first
this.main.style.minHeight = window.innerHeight - (this.footer?.offsetHeight ?? 0) + "px";
this.main.style.paddingTop = (this.header?.offsetHeight ?? 0) + "px";
}
差不多;可能看起来有点不同,但那是你的问题,不是我的问题。
可能想要在ngOnInit
或ngAfterViewInit
方法中调用它,这样它就可以在第一次加载时设置好(否则它只会在窗口调整大小时触发)…
public ngAfterViewInit(): void {
this.resizeLayout();
}
这可以摆脱你的额外的脚本,并保持它完全包含在应用程序本身-触发一次,当应用程序(视图)第一次初始化,然后在任何窗口大小调整完成后。
对于CSS所能做的事情来说,这是很大的努力。
- 使用CSS - flex
我更喜欢使用Angular flex布局而不是原始的CSS,因为1)它更容易,2)我个人喜欢将基本页面的结构细节与基本页面本身(HTML)保持在一起。
正因为如此,我对基础CSS flex细节的记忆非常差,所以我将在模板中以AFL形式给你:
<div id="app-container"
fxFlexFill
fxLayout="column"
fxLayoutAlign="stretch stretch">
<div id="header" fxFlex="100px">...</div>
<div id="main" fxFlex>
<router-outlet></router-outlet>
</div>
<div id="footer fxFlex="50px">...</div>
</div>
只要你适当地设置你的html/body样式为flex布局,这将:
- fxFlexFill:导致app-container填充可用空间(例如,如果你有
body { width: 100vw; height: 100vh; }
,那么app-container现在填充整个窗口) - fxLayout="column":导致子元素呈现在页面下方(行为横)
- fxLayoutAlign="stretch ":使子元素上下拉伸
紧跟子元素:
- fxFlex="100px":限制标题div只'拉伸'到100px
- fxFlex:允许主div尽可能拉伸
- fxFlex="50px":限制页脚div只'拉伸'到50px
有一些额外的东西需要使它工作得更好一点,并完全按照你想要的方式工作(例如#main { overflow: auto; }
),但这得到了你想要的布局的90%的方式,没有实际的脚本,只是CSS。