Angular学习之以Tooltip为例了解自定义指令
本篇文章带大家继续angular的学习,以Tooltip为例来了解一下自定义指令,希望对大家有所帮助!
在之前的文章中,我们已经概览了 Angular
的相关内容。在自定义指令的部分,我们已经能够实现编写,但是,在实际场景中,我们还需要标准化的管理。
Angular 是 Angular.js 的升版。
So,本文,我们就以 Tooltip
来讲解下自定义指令的内容。
线上效果图,如下:
目录结构
在上一篇文章的实现的代码项目基础上,执行命令行:
- # 进入 directives 文件夹
- $ cd directives
- # 创建 tooltip 文件夹
- $ mkdir tooltip
- # 进入 tooltip 文件夹
- $ cd tooltip
- # 创建 tooltip 组件
- $ ng generate component tooltip
- # 创建 tooltip 指令
- $ ng generate directive tooltip
执行完上面的命令行之后,你会得到 app/directive/tooltip
的文件目录结构如下:
- tooltip
- ├── tooltip // tooltip 组件
- │ ├── user-list.component.html // 页面骨架
- │ ├── user-list.component.scss // 页面独有样式
- │ ├── user-list.component.spec.ts // 测试文件
- │ └── user-list.component.ts // javascript 文件
- ├── tooltip.directive.spec.ts // 测试文件
- └── tooltip.directive.ts // 指令文件
嗯,这里我将组件放在 tooltip
的同级,主要是方便管理。当然,这个因人而异,你可以放在公共组件 components
文件夹内。
编写 tooltip 组件
在 html
文件中,有:
- <div class="caret"></div>
- <div class="tooltip-content">{{data.content}}</div>
在样式文件 .scss
中,有:
- $black: #000000;
- $white: #ffffff;
- $caret-size: 6px;
- $tooltip-bg: transparentize($black, 0.25); // transparentize 是 sass 的语法
- $grid-gutter-width: 30px;
- $body-bg-color: $white;
- $app-anim-time: 200ms;
- $app-anim-curve: ease-out;
- $std-border-radius: 5px;
- $zindex-max: 100;
- // :host 伪类选择器,给组件元素本身设置样式
- :host {
- position: fixed;
- padding: $grid-gutter-width/3 $grid-gutter-width/2;
- background-color: $tooltip-bg;
- color: $body-bg-color;
- opacity: 0;
- transition: all $app-anim-time $app-anim-curve;
- text-align: center;
- border-radius: $std-border-radius;
- z-index: $zindex-max;
- }
- .caret { // 脱字符
- width: 0;
- height: 0;
- border-left: 6px solid transparent;
- border-right: 6px solid transparent;
- border-bottom: 6px solid $tooltip-bg;
- position: absolute;
- top: -$caret-size;
- left: 50%;
- margin-left: -$caret-size/2;
- border-bottom-color: $tooltip-bg;
- }
嗯~,css
是一个神奇的东西,之后会安排一篇文章来讲解下 sass
相关的内容...
然后,在 javascript
文件 tooltip.component.ts
内容如下:
- import {
- Component,
- ElementRef, // 元素指向
- HostBinding,
- OnDestroy,
- OnInit
- } from '@angular/core';
- @Component({
- selector: 'app-tooltip', // 标识符,表明我这个组件叫做啥,这里是 app-tooltip
- templateUrl: './tooltip.component.html', // 本组件的骨架
- styleUrls: ['./tooltip.component.scss'] // 本组件的私有样式
- })
- export class TooltipComponent implements OnInit {
- public data: any; // 在 directive 上赋值
- private displayTimeOut:any;
- // 组件本身 host 绑定相关的装饰器
- @HostBinding('style.top') hostStyleTop!: string;
- @HostBinding('style.left') hostStyleLeft!: string;
- @HostBinding('style.opacity') hostStyleOpacity!: string;
- constructor(
- private elementRef: ElementRef
- ) { }
- ngOnInit(): void {
- this.hostStyleTop = this.data.elementPosition.bottom + 'px';
- if(this.displayTimeOut) {
- clearTimeout(this.displayTimeOut)
- }
- this.displayTimeOut = setTimeout((_: any) => {
- // 这里计算 tooltip 距离左侧的距离,这里计算公式是:tooltip.left + 目标元素的.width - (tooltip.width/2)
- this.hostStyleLeft = this.data.elementPosition.left + this.data.element.clientWidth / 2 - this.elementRef.nativeElement.clientWidth / 2 + 'px'
- this.hostStyleOpacity = '1';
- this.hostStyleTop = this.data.elementPosition.bottom + 10 + 'px'
- }, 500)
- }
- // 组件销毁
- ngOnDestroy() {
- // 组件销毁后,清除定时器,防止内存泄露
- if(this.displayTimeOut) {
- clearTimeout(this.displayTimeOut)
- }
- }
- }
编写 tooltip 指令
这是本文的重点,具体的说明,我在代码上标注出来~
相关的文件 tooltip.directive.ts
内容如下:
- import {
- ApplicationRef, // 全局性调用检测
- ComponentFactoryResolver, // 创建组件对象
- ComponentRef, // 组件实例的关联和指引,指向 ComponentFactory 创建的元素
- Directive, ElementRef,
- EmbeddedViewRef, // EmbeddedViewRef 继承于 ViewRef,用于表示模板元素中定义的 UI 元素。
- HostListener, // DOM 事件监听
- Injector, // 依赖注入
- Input
- } from '@angular/core';
- import { TooltipComponent } from './tooltip/tooltip.component';
- @Directive({
- selector: '[appTooltip]'
- })
- export class TooltipDirective {
- @Input("appTooltip") appTooltip!: string;
- private componentRef!: ComponentRef<TooltipComponent>;
- // 获取目标元素的相关位置,比如 left, right, top, bottom
- get elementPosition() {
- return this.elementRef.nativeElement.getBoundingClientRect();
- }
- constructor(
- protected elementRef: ElementRef,
- protected appRef: ApplicationRef,
- protected componentFactoryResolver: ComponentFactoryResolver,
- protected injector: Injector
- ) { }
- // 创建 tooltip
- protected createTooltip() {
- this.componentRef = this.componentFactoryResolver
- .resolveComponentFactory(TooltipComponent) // 绑定 tooltip 组件
- .create(this.injector);
- this.componentRef.instance.data = { // 绑定 data 数据
- content: this.appTooltip,
- element: this.elementRef.nativeElement,
- elementPosition: this.elementPosition
- }
- this.appRef.attachView(this.componentRef.hostView); // 添加视图
- const domElem = (this.componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
- document.body.appendChild(domElem);
- }
- // 删除 tooltip
- protected destroyTooltip() {
- if(this.componentRef) {
- this.appRef.detachView(this.componentRef.hostView); // 移除视图
- this.componentRef.destroy();
- }
- }
- // 监听鼠标移入
- @HostListener('mouseover')
- OnEnter() {
- this.createTooltip();
- }
- // 监听鼠标移出
- @HostListener('mouseout')
- OnOut() {
- this.destroyTooltip();
- }
- }
到这里,已经完成了 99%
的功能了,下面我们在页面上调用即可。
页面上调用
我们在 user-list.component.html
上添加下面的内容:
- <p style="margin-top: 100px;">
- <!-- [appTooltip]="'Hello Jimmy'" 是重点 -->
- <span
- [appTooltip]="'Hello Jimmy'"
- style="margin-left: 200px; width: 160px; text-align: center; padding: 20px 0; display: inline-block; border: 1px solid #999;"
- >Jimmy</span>
- </p>
TooltipDirective
这个指令我们已经在 app.module.ts
上进行声明,我们直接调用即可。目前的效果如下:
我们实现的 tooltip
是底部居中展示,也就是我们平常使用框架,比如 angular ant design
中 tooltip
的 bottom
属性。对于其他属性,读者感兴趣的话,可以进行扩展。
至此,我们可以很好的维护自己编写的指令文件了。
本文网址:https://www.zztuku.com/detail-11578.html
站长图库 - Angular学习之以Tooltip为例了解自定义指令
申明:本文转载于《掘金社区》,如有侵犯,请 联系我们 删除。
您还没有登录,请 登录 后发表评论!
提示:请勿发布广告垃圾评论,否则封号处理!!