如果你已经是编写Angular应用的”老手“,可能会觉得这篇文章介绍的这些特性自己肯定都很熟悉。但事实未必如此,不信的话等你看完再说。
Title标签是一个HTML元素,用于指定网页标题。Title标签作为给定结果的可点击标题,显示在搜索引擎结果页面(SERP)上。它们对于可用性、SEO和社交共享而言至关重要。
Angular应用使用index.html中的…,在浏览器窗口中设置标题。导航到Angular中的组件不会更改标题。
那么你知道吗,其实可以通过组件来设置浏览器标题。
Angular在@angular/platform-browser中有一个Title服务。我们只需将Title服务注入到组件中,并使用setTitle方法设置标题即可。
import { Title } from "@angular/platform-browser"
@Component({
...
})
export class LoginComponent implements OnInit {
constructor(private title: Title) {}
ngOnInit() {
title.setTitle("Login")
}
}
当我们导航到LoginComponent时,浏览器的标题将设置为“Login”。
我们可以在项目的所有组件中重复这一操作,这样在导航到它们的位置时,浏览器窗口将更改为组件设置的标题。
我们的Angular应用渲染的内容大部分来自于index.html。我们的应用会拥有在index.html中设置的一个meta标签。Angular在@angular/platform-browser中有一个Meta服务,使我们能够从组件中设置meta标签。
这是很有用的功能,可以更好地进行搜索引擎优化(SEO),也可以将组件拥有的页面共享给社交媒体。
根据维基百科的定义:
Meta是HTML和XHTML文档中使用的标签,用于提供网页的结构化元数据。它们是网页head的一部分,可以在同一页面上使用具有不同属性的多个Meta元素。Meta元素可用于指定页面描述、关键字,以及其他head元素和属性未提供的元数据。
Meta元素提供有关网页的信息,搜索引擎可以在这些信息的帮助下正确地分类网页。
它用起来非常容易,只需从@angular/platform-browser导入Meta,并将其注入到我们的组件中即可。
import { Meta } from "@angular/platform-browser"
@Component({
...
})
export class BlogComponent implements OnInit {
constructor(private meta: Meta) {}
ngOnInit() {
meta.updateTag({name: "title", content: ""})
meta.updateTag({name: "description", content: "Lorem ipsum dolor"})
meta.updateTag({name: "image", content: "./assets/blog-image.jpg"})
meta.updateTag({name: "site", content: "My Site"})
}
}
有了它,我们的BlogComponent可以渲染在Facebook和Twitter等网页上,并带有我们组件的描述信息,提供标题、图像和注释。
这个你也听过吗?
我们都在模板中使用默认模板插值器{{}}来显示组件中的属性。
开头为{{,结尾为}}。如果我们在它们之间放置一个属性成员,它将渲染在浏览器DOM上。
你知道我们可以用自己的符号覆盖默认的封装开始和结束定界符吗?很简单,在Component装饰器的interpolation属性中指定即可。
@Component({
interpolation: ["((","))"]
})
export class AppComponent {
AppComponent模板中使用的插值将不再是“{{}}”,而是“(())”。
@Component({
template: `
<div>
((data))
</div>
`,
interpolation: ["((","))"]
})
export class AppComponent {
data: any = "dataVar"
}
在渲染时,将渲染“dataVar”以代替((data))。
我们可以使用Location服务获取当前浏览器窗口的URL。根据所使用的LocationStrategy,Location将存储URL的路径或URL的哈希段。
有了Location,我们可以转到一个URL,在平台的历史记录中向前或向后跳转,更改浏览器URL,替换平台的历史记录栈中的顶部项等。
我们从CommonModule注入Location服务,就可以使用它了。
import { Location } from "@angular/common"
@Component({
...
})
export class AppComponent {
constructor(private location: Location) {}
navigatTo(url) {
this.location.go(url)
}
goBack() {
location.back()
}
goForward() {
location.forward()
}
}
有时我们想要获取文档模型,以便我们可以从Angular应用中执行DOM操作。
使用DOCUMENT就可以做到这一点。DOCUMENT是表示主要渲染上下文的DI令牌。在浏览器中这就是DOM文档。它以与环境无关的方式提供DOM操作。
注意:当应用程序上下文和渲染上下文不同时(例如将应用程序运行到Web Worker中时),Document可能在应用程序上下文中不可用。
假设我们在html中有一个元素:
<canvas id="canvas"></canvas>
我们可以注入DOCUMENT来获取画布HTMLElement:
@Component({
})
export class CanvasElement {
constructor(@Inject(DOCUMENT) _doc: Document) {}
}
我们可以调用getElementById(),获得画布的HTMLElement。
@Component({
})
export class CanvasElement {
constructor(@Inject(DOCUMENT) _doc: Document) {}
renderCanvas() {
this._doc.getElementById("canvas")
}
}
我们还可以使用ElementRef和模板引用来安全地执行此操作,理解即可。
警告:要小心!直接与DOM交互是危险的,并且可能带来XSS风险。
我们在Angular应用中主要使用Component、Module和Directive装饰器。
我们有一个Attribute装饰器,它使我们能够消除对静态字符串的更改检测,这样在传递静态字符串时就不会降低性能了。
Attribute装饰器的值只检查一次,之后就不再检查了。它们的用法类似于@Input装饰器:
@Component({
...
})
export class BlogComponent {
constructor(@Attribute("type") private type: string ) {}
}
就像美国的防空网一样,这是Angular中非常强大的功能。它会拦截HttpRequest并处理它们。
大多数拦截器会在调用next.handle(transformedReq),以将传出请求传递到链中的下一个拦截器之前对请求进行转换。
在极少数情况下,拦截器可能希望自己完全处理请求,而不是委托给链的其余部分。这种行为是允许的。
HttpInterceptor可用于:
它用起来很简单,首先创建一个服务并实现HttpInterceptor接口。
@Injectable()
export class MockBackendInterceptor implements HttpInterceptor {
constructor() {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
...
}
}
然后将其它插入你的主模块中:
@NgModule({
...
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: MockBackendInterceptor,
multi: true
}
]
...
})
export class AppModule {
有时我们确实希望在Angular应用启动时运行一段代码,这段代码可能会加载一些设置,比如加载缓存,加载配置或进行某些签入。AppInitialzer令牌可以帮助你解决这一问题。
APP_INITIALIZER:初始化应用时执行的函数。
它很容易使用。如果我们希望在Angular应用启动时执行以下runSettings函数:
function runSettingsOnInit() {
...
}
只需转到主要模块AppModule,并将它添加到其NgModule装饰器中的provider部分:
@NgModule({
providers: [
{ provide: APP_INITIALIZER, useFactory: runSettingsOnInit }
]
})
就像AppInitializer一样,Angular还有一项功能,使我们能够在引导组件时进行侦听。它就是APP_BOOTSTRAP_LISTENER。
通过此令牌提供的所有回调将为每个引导的组件调用。
我们有很多理由来侦听组件引导,例如,Router模块使用它来破坏和创建基于路由导航的组件。
要使用APP_BOOTSTRAP_LISTENER,请使用回调函数将其添加到AppModule的provider部分中:
@NgModule({
{
provide: APP_BOOTSTRAP_LISTENER, multi: true,
useExisting: runOnBootstrap
}
...
})
export class AppModule {}
复数表示是一个问题。我们需要一直根据单数/复数值来在我们的应用中正确定义语法。某些网站会使用(s)。比如:
1 component(s) removed
3 component(s) removed
读者应该在阅读时自行删除或添加(s)****。
Angular在其NgPlural指令中为我们解决了这个问题。
NgPlural基于数字值来添加/删除DOM子树,为复数量身定制。
显示与切换表达式值匹配的DOM子树,否则显示与切换表达式的复数类别匹配的DOM子树。
要使用此指令,你必须提供一个容器元素,该元素将[ngPlural]属性设置为一个switch表达式。具有[ngPluralCase]的内部元素将根据其表达式显示:
<p [ngPlural]="components">
<ng-template ngPluralCase="=1">1 component removed</ng-template>
<ng-template ngPluralCase=">1">{{components}} components removed </ng-template>
</p>
看到了吧,当显示“已删除的组件”数量时,我们使用NgPlural指令删除了(s)。它将显示:
// if 1 component
1 component removed
// if 5 components
5 components removed
全篇看下来,有没有丧失信心、觉得自己老了?
不用担心,我们所有人都有知识盲区。上面所列的内容只是其中一部分,Angular既庞大又复杂。可以试着查看其他Angular相关的内容,看看是否可以找出你以前从未听说过的特性。期待你的发现。
领取专属 10元无门槛券
私享最新 技术干货