使用指令在 Angular 中实现全屏切换功能。
我们将看到如何利用指令的力量来创建一个超级简单的全屏切换功能。
让我们看看 Angular 中指令的定义:
指令是为 Angular 应用中元素添加额外行为的类。使用 Angular 的内置指令,你可以管理表单、列表、样式以及用户看到的内容。
正如定义所说,我们可以使用它为元素添加额外的行为。如果这还不够酷,我就不知道还有什么酷了。
这是我的一个项目中该指令的一个小演示(https://cartella.sreyaj.dev)
Angular 中的指令
对于刚开始使用 Angular 的人来说,指令这个术语及其工作原理可能会令人困惑。大多数人只会使用一些最常见的指令,例如
- NgClass
- NgStyle
- NgIf
- NgFor
我们其实不必关心添加 this 后会如何神奇地实现这些功能。我们可能知道,要有条件地渲染一个元素,可以使用*ngIf
and ,只有当条件成立时才渲染该元素。故事就到此为止!
我想给那些正在掌握 Angular 的人的一条建议是尝试深入研究这些功能并尝试找到底层实现。
Angular 提供了非常详尽的文档,讲解了不同类型的指令及其使用方法。阅读链接:
https://angular.io/guide/built-in-directives#built-in-directives
提示:要查看内置指令是如何编写的,只需访问其 API 文档页面并单击code
图标即可转到 repo 中的直接文件:
创建全屏指令
所以今天我们将构建一个自定义指令,它将帮助我们实现一项功能——最大化和最小化元素。
话不多说,让我们开始吧。
1. 为我们的指令创建一个模块
这实际上是可选的。但我确实喜欢创建一个模块,然后从这个模块声明并导出该指令。然后,只要我需要这个功能,我就会导入这个模块。
import { NgModule } from "@angular/core";
import { MaximizeDirective } from "./maxmimize.directive";
@NgModule({
declarations: [MaximizeDirective],
exports: [MaximizeDirective] //<-- Make sure to export it
})
export class MaximizeModule {}
2.创建指令
接下来我们创建指令。我称之为maximize
指令。创建指令后,我们来添加逻辑。
其基本思想是将元素(指令所在的位置)的宽度和高度设置为100vw
,100vh
使其覆盖整个屏幕空间。在某些情况下,您可能还需要更改元素的位置。
import { Directive, ElementRef, Renderer2 } from "@angular/core";
import { BehaviorSubject } from "rxjs";
import { tap } from "rxjs/operators";
@Directive({
selector: "[maximize]",
exportAs: "maximize" // <-- Make not of this here
})
export class MaximizeDirective {
private isMaximizedSubject = new BehaviorSubject(false);
isMaximized$ = this.isMaximizedSubject.asObservable();
constructor(private el: ElementRef, private renderer: Renderer2) {}
toggle() {
this.isMaximizedSubject?.getValue() ? this.minimize() : this.maximize();
}
maximize() {
if (this.el) {
this.isMaximizedSubject.next(true);
this.renderer.addClass(this.el.nativeElement, "fullscreen");
}
}
minimize() {
if (this.el) {
this.isMaximizedSubject.next(false);
this.renderer.removeClass(this.el.nativeElement, "fullscreen");
}
}
}
让我为你们分解一下代码。
首先,我们需要获取应用该指令的元素。我们通过ElementRef
在构造函数中注入来实现。这将提供对该元素的引用。
接下来,我们保留一个主题来维护指令的状态(以了解我们当前是最小化还是最大化)。
修改元素属性
因此我定义了一个 CSS 类,它只修改高度和宽度:
.fullscreen {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
}
现在的想法是,当用户希望它处于全屏模式时,切换这个类。为此,我们掌握了Renderer2
( Doc ),这是一种在 Angular 中操作 DOM 元素的好方法。
因此,编写两个函数,一个用于添加类,一个用于删除类。当调用这两个函数时,我们会更新状态。
添加了另一个函数,toggle
以便用户无需了解当前状态即可执行操作。
导出指令实例
在上面的部分中,我标记了特定的一行代码:
@Directive({
selector: "[maximize]",
exportAs: "maximize" // <-- Make not of this here
})
这是 Angular 提供的一个非常有趣的功能。在指令中,我们可以指定是否要在模板中启用该实例。
阅读此处:https://angular.io/api/core/Directive#exportas
它的作用是使用指定的名称在模板中提供指令实例:
<div class="card" maximize #maximize="maximize">
<p>{{(maximize.isMaximized$ | async)}}</p>
</div>
isMaximized$
看看我是如何在模板中访问指令的属性的。同样,指令的所有公共属性都可以使用 访问maximize
。
用法
要使用该指令,首先我在我的 中导入该模块AppModule
。如果您已经在 中声明了该指令AppModule
,则可以跳过此步骤。
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { AppComponent } from "./app.component";
import { MaximizeModule } from "./maximize/maximize.module";
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, MaximizeModule], // <-- Imported the module
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
在您的模板中,您现在可以将指令添加到任何元素
<div class="card" maximize #maximize="maximize">
<button class="min-button"
(click)="maximize.minimize()">
</button>
<button class="max-button"
(click)="maximize.maximize()">
</button>
</div>
因此,就像我们在讨论获取实例的部分中看到的那样,我们可以获取指令中的minimize()
和函数来分别应用/删除类。maximize()
额外福利 - 浏览器也可全屏显示
所以我们所做的只是最大化元素,但您还想让浏览器全屏显示,我们也可以添加它。
- 安装
screenfull
库
npm i screenfull
- 像这样更新指令:
...
import * as Fullscreen from "screenfull"; // <-- add the import
...
maximize() {
if (this.el) {
this.isMaximizedSubject.next(true);
this.renderer.addClass(this.el.nativeElement, "fullscreen");
if (Fullscreen.isEnabled) {
Fullscreen.request(); // <-- request fullscreen mode
}
}
}
minimize() {
if (this.el) {
this.isMaximizedSubject.next(false);
this.renderer.removeClass(this.el.nativeElement, "fullscreen");
if (Fullscreen.isEnabled) {
Fullscreen.exit(); // <-- exit fullscreen mode
}
}
}
注意:您可能需要在单独的窗口中打开沙盒预览以使全屏工作正常,或者直接访问此预览 URL:https://x6epr.csb.app/
代码
请在评论区留言,分享你的想法。
注意安全❤️