PHP程序员小白到大牛集训(12期免息)
作者信息

青灯夜游

今天学习一小步,明天提升一大步

最近文章
php怎么去掉含字符串的数组元素606
php怎么只输出数组键值188
php关联数组中怎么去掉空值798
视频教程分类
推荐视频教程
  • php程序员小白到大牛三个月集训php程序员小白到大牛三个月集训
  • Laravel 9 学习正当时—保姆级教程,想学不会都难!Laravel 9 学习正当时—保姆级教程,想学不会都难!
  • 千万级数据并发解决方案(理论+实战)千万级数据并发解决方案(理论+实战)
  • Laravel基础与实战(模块化)Laravel基础与实战(模块化)
  • 首页 >web前端 >js教程 > 正文

    Angular学习之以Tooltip为例了解自定义指令

    转载2022-04-13 21:03:40723 关注公众号:每天精选资源文章推送
    本篇文章带大家继续angular的学习,以Tooltip为例来了解一下自定义指令,希望对大家有所帮助!

    在之前的文章中,我们已经概览了 Angular 的相关内容。在自定义指令的部分,我们已经能够实现编写,但是,在实际场景中,我们还需要标准化的管理。

    Angular 是 Angular.js 的升版。【相关教程推荐:《angular教程》】

    So,本文,我们就以 Tooltip 来讲解下自定义指令的内容。

    线上效果图,如下:

    1.png

    目录结构

    在上一篇文章的实现的代码项目基础上,执行命令行:

    # 进入 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 上进行声明,我们直接调用即可。目前的效果如下:

    2.png

    我们实现的 tooltip 是底部居中展示,也就是我们平常使用框架,比如 angular ant designtooltipbottom 属性。对于其他属性,读者感兴趣的话,可以进行扩展。

    至此,我们可以很好的维护自己编写的指令文件了。

    更多编程相关知识,请访问:编程入门!!

    以上就是Angular学习之以Tooltip为例了解自定义指令的详细内容,更多请关注php中文网其它相关文章!

    20期PHP线上班

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除

    相关文章

    相关视频


    专题推荐