为啥文档为空?
Posted
技术标签:
【中文标题】为啥文档为空?【英文标题】:Why is document null?为什么文档为空? 【发布时间】:2018-01-07 08:35:34 【问题描述】:**已更新**,解决方案接近工作:
我正在尝试让我的“跳转到内容”链接跳转到“#content-start”之后的第一个可聚焦元素。
登录-base.component.ts:
import Component, OnInit from '@angular/core';
import Inject, Injectable from '@angular/core';
import DOCUMENT from '@angular/platform-browser';
@Component(
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
)
export class BaseLoginComponent implements OnInit
constructor(
@Inject(DOCUMENT) private document: any
)
skip()
console.log(document);
console.log(document.querySelector);
var content = document.querySelector(`#content-start`); // ?? document is null!!
if (content)
var control = content.querySelector('input, button, a');
console.log(control);
//if (control)
// control.focus(); // first only
//
;
ngOnInit()
this.document.getElementById('skipLink').onclick = this.skip;
this.document.getElementById('skipLink').onkeypress = function (e)
if (e.keyCode == 13)
this.skip();
login.component.html:
<div class="login-page">
<section class="main container" id="content-start">
<input type="text"/>
这确实有效,因为 console.log(control) 返回
<input _ngcontent-c4="" id="username" name="username">
这实际上是正确的控制。
但我不能只设置 .focus(),因为我拥有的是 HTML sn-p,而不是带有方法的对象,例如 .focus();
呃,有 jQuery 的 $(control) 的 Angular 等价物吗?
【问题讨论】:
离题。@Component
扩展自 @Injectable
,无需使用 @Injectable
注释您的组件
***.com/questions/37521298/… 也许这将有助于假设您的文档注入不起作用
【参考方案1】:
这是因为 DOM 尚未加载到 ngOnInit
中。更新你的代码看起来像这样,实现AfterViewInit
:
export class AppComponent implements AfterViewInit
constructor(
@Inject(DOCUMENT) private document: any
)
ngAfterViewInit()
this.document.getElementById('skipLink').onclick = skipLink;
this.document.getElementById('skipLink').onkeypress = function (e)
if (e.keyCode == 13)
skipLink();
function skipLink()
let content: HTMLElement = this.document.querySelector("#content-start"); // ?? document is null!!
if (content)
let control: HTMLElement = this.document.querySelector('input, button, a');
console.log(control);
if (control)
// control.focus(); // first only
ngAfterViewInit
就像它听起来的那样;它仅在最初加载视图后运行。
根据您的问题进行编辑:您正在寻找angular.element。这方面的文档真的很有帮助,并且是在 Angular 中操作元素的更好的编程实践。
【讨论】:
这没什么区别。相同的“未定义”错误。我已将代码从 app.component 移到 login-base-component 以确保我没有任何跨组件问题。 (开篇已更新)。现在我没有收到任何错误,但仍然无法访问控件来聚焦它。 有趣。您是否尝试过angular.element
(具体是.find()
函数)? (作为说明,即使它没有任何区别,我还是建议使用ngAfterViewInit
作为更好的编程习惯)
编辑:错误:“找不到名称 'angular'”(这是 Ang2)
你有 Jquery 吗?无论哪种方式,这里都解释了另一个(甚至可能更好)的解决方案:Using ViewChild in Angular to Access a Child Component, Directive or DOM Element
不知道如何实现它。此外,仅访问 DOM 元素似乎非常困难。让我觉得我只关注一个元素是错误的。【参考方案2】:
正如您所发现的,skipLink
应该是您的组件类的一个方法。为了在skipLink
内部保持正确的this
,您可以使用addEventListener
和箭头函数设置事件处理程序:
public ngOnInit()
this.document.getElementById('skipLink').addEventListener("click", () =>
this.skipLink();
);
this.document.getElementById('skipLink').addEventListener("keypress", (e) =>
if (e.keyCode == 13)
this.skipLink();
private skipLink()
let control: HTMLElement = this.document.querySelector('input, button, a');
if (control)
control.focus();
您可以在this plunker 中查看代码。
正如Kevin 所述,使用ViewChild
是一种更标准的方式来引用组件中的元素。您可以在目标元素上定义一个模板引用变量(例如下面组件模板中的#firstButton
),使用ViewChild
获取对它的引用,并使用nativeElement
属性获取HTML 元素本身。至于事件处理程序,您可以使用 Angular 绑定来设置它们(例如(click)="skipLink()"
)。
该方法显示在this plunker:
import Component, NgModule, Inject, ElementRef, ViewChild from '@angular/core';
...
@Component(
selector: 'my-app',
template: `
<button #firstButton>Focusable Button</button>
<br/>
<button (click)="skipLink()">Click here to set focus on first button</button>
`,
...
)
export class App
@ViewChild("firstButton") private firstButton: ElementRef;
private skipLink()
this.firstButton.nativeElement.focus();
【讨论】:
很好的解释,我忘记了箭头函数。【参考方案3】:这与最初的实现相差甚远;如果我更新开头的帖子,那么 cmets 将毫无意义。
按照 Kevin 的建议按照 Using ViewChild in Angular to Access a Child Component, Directive or DOM Element 实施,(除非我有误解):
import Component, ViewChild, AfterViewInit, ElementRef from '@angular/core';
export class AppComponent
@ViewChild('firstControl') firstControl: ElementRef;
skipLink()
console.log(this.firstControl);
//if (this.firstControl) this.firstControl.focus();
;
.
<a href="#content-start" id="skipLink" (click)="skipLink()">Skip to main content</a>
不幸的是,这也好不到哪里去。 this.firstControl 未定义。
【讨论】:
你可以看看my answer。它显示了一个代码示例,以及一个您可以尝试的工作 plunker(相关代码在文件 src/app.ts 中)。以上是关于为啥文档为空?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 Service Worker 的推送事件数据/有效负载为空?
为啥我的 response.body 为空,而我的后端设备令牌为空?