上篇博客提到了在Angular2+Ioinc环境APP中实现手势识别,过了一会儿我想到可以使用Angular2指令的方式将这个识别功能指令化,简单复用到所有页面.
Angular2指令Directive是一种靠依赖注入的方式提供一系列封装功能.这种依赖注入在使用层面是DOM级的,例如
<div *slide="'up'">
可以利用它执行两种功能:
1.属性指令,可以用于改变当前DOM的属性,类似的原生指令有[ngClass][ngStyle],具体在这篇不展开;
2.结构指令,可以用于改变当前DOM的结构,类似的原生指令有*ngFor *ngIf.我将上下滑动页面触发隐藏的功能封装为一个自定义指令 *slide.具体使用方法是:
<div *slide="'up'">
<div *slide="'down'">
当向上滑动时包含'up'属性的标签组会显示'down'会隐藏,当向下滑动时包含'down'属性的标签组会显示'up'会隐藏.废话不多说,让我们看看具体实现.
首先是指令类slide.directive.ts
import {Directive, TemplateRef,ElementRef, HostListener, Renderer,Input,ViewContainerRef} from '@angular/core'; //指令装饰器,每个指令都需要 @Directive({ selector: '[slide]' }) //指令类,这里类名是之前起的,不要管 export class HighlightDirective { //记录初始Y坐标的变量 public OrClientY //依赖注入,DOM对象,视图控制对象,视图对象 constructor(elem: ElementRef,private viewContainer:ViewContainerRef,private templateRef:TemplateRef<any>) { } //输入装饰器,用来接收从组件中传来的属性,在模板中可以看到 @Input('slide') //输入后用来执行的函数,主要逻辑在里面 set ffff(direction:string){ let _this = this //起始让up属性的容器显示 if(direction=='up'){ //渲染容器 _this.viewContainer.createEmbeddedView(_this.templateRef); } //监听开始触碰,记录坐标Y document.addEventListener('touchstart', function(e: MouseEvent) { _this.OrClientY = event['targetTouches'][0].clientY }); //监听触碰结尾 document.addEventListener('touchend', function(e: MouseEvent) { if(event['changedTouches'][0].clientY>_this.OrClientY){ //下滑,判定为下滑,页面一开一合 if(direction=='up'){ _this.viewContainer.createEmbeddedView(_this.templateRef); }if(direction=='down'){ _this.viewContainer.clear(); } }else if(event['changedTouches'][0].clientY<_this.OrClientY){ //上滑 if(direction=='down'){ _this.viewContainer.createEmbeddedView(_this.templateRef); }if(direction=='up'){ _this.viewContainer.clear(); } } }); } }
大部分注释已经写了.接下来要做的是把指令类包装到Angular2的灵魂----模块之中.
我建了一个指令模块,用来导出所有的指令,将来把这个指令模块导入到某个页面的module.ts之中就可以使用指令了!
具体代码:
import { NgModule } from '@angular/core'; import { MinValidatorDirective } from './min-validator/min-validator'; import { HighlightDirective } from './highlight/highlight.directive'; import { OverslideDirective } from './overslide/overslide'; import { MaxValidatorDirective } from './max-validator/max-validator'; @NgModule({ declarations: [ MinValidatorDirective, HighlightDirective, OverslideDirective, MaxValidatorDirective, ], imports: [], exports: [ MinValidatorDirective, HighlightDirective, OverslideDirective, MaxValidatorDirective, ] }) export class DirectivesModule {}
最后一步是导入进页面module.ts
import { NgModule } from '@angular/core'; import { IonicPageModule } from 'ionic-angular'; import { AcsQrcodePage } from './acs_qrcode'; import { BarcodeScanner } from '@ionic-native/barcode-scanner'; import { NgxQRCodeModule } from 'ngx-qrcode2'; import {DirectivesModule} from '../../../directives/directives.module' @NgModule({ declarations: [ AcsQrcodePage, ], imports: [ IonicPageModule.forChild(AcsQrcodePage) , NgxQRCodeModule, //指令模块在这里 DirectivesModule ], }) export class AcsQrcodePageModule {}
完成以上繁琐工作后,就可以使用了.核心代码如下:
<!--注意这里--> <div *slide="'up'"> <ion-card style="width:auto;height:70%;margin-top: 40px;display: flex;flex-direction:column" *ngIf="createdCode"> <div style="width:100%;height:70px;display:flex;justify-content:space-between;padding:10px 20px;"> <div style="height:50px;width:50px;border-radius: 3px;overflow: hidden;"> <img src="{{handimgs(user.photo_url)}}" style="width:100%;height:100%;"/> </div> <div style="height:100%;width:calc(100% - 50px);padding-left:10px;"> <p id='real_name'style="margin:0;width:100%;height:35px;font-size:1.8rem;">{{user.real_name}}</p> <p style="margin:0;width:100%;height:15px;font-size:1.3rem;">{{user.dept_name}}</p> <div style="height:20px;width:20px;position:relative;top:-95%;left: 30%;z-index: 100"> <img src={{this.selectPicByGender(user.gender)}} style="width:100%;height:100%;"/> </div> </div> </div> <div style="height:50%;width:80%"> <img src="assets/img/ngx-qrcode.png" style="height:48%;width:80%;position:absolute;top:22%;left:10%;z-index: 0"> <ngx-qrcode style="height:40%;width:40%;position:absolute;top:32%;left:30%;z-index: 99" [qrc-version] = "8"[qrc-value]="createdCode"></ngx-qrcode> <div style="height:30px;width:30px;border-radius: 3px;overflow: hidden;position:absolute;top:41%;left: 46%;z-index: 100"> <img src="{{handimgs(user.photo_url)}}" style="width:100%;height:100%;"/> </div> </div> <div style="width:94.5%;color:#999;position: absolute;top: 72%;z-index: 222;text-align: center">扫一扫,打卡闸机</div> </ion-card> <ion-row text-center tappable> <p style="margin:30px 0 5px 0;width:100%;"><img src="assets/lifehome/arrow.png" style="width:25px;transform:rotateZ(180deg);"/></p> <p style="margin:0;width:100%;color:#fff;">上滑查看所属楼宇信息</p> </ion-row> </div> <!--注意这里--> <div *slide="'down'"> <ion-row text-center tappable> <p style="width:100%;margin:0;"><img src="assets/lifehome/arrow.png" style="width:25px;"/></p> <p style="margin:5px 0 30px 0;width:100%;color:#fff;">下滑返回闸机二维码</p> </ion-row> <ion-card *ngIf="isShowStatus"> <ion-row style="margin-top:5px;padding:0 10px;border-bottom:1px solid #333;" *ngFor=" let item of statusList"> <ion-col text-left>楼宇:{{item.building_name}}(闸机群){{item.gate_machine_group_name}}</ion-col> <ion-col text-right style="color:#c33;" *ngIf="(item.bind_state=='部分失败')">部分失败</ion-col> <ion-col text-right style="color:greenyellow;" *ngIf="(item.bind_state=='绑定成功')">绑定成功</ion-col> </ion-row> </ion-card> <ion-card *ngIf="!isShowStatus"> <ion-row style="margin-top:5px;padding:0 10px;"> <ion-col text-left >{{nobindTipWord}}</ion-col> </ion-row> </ion-card> </div>
两个地方使用指令*slide,分别对应上滑和下滑需要显示的页面,即可以实现.仅此而已!不需要在页面TS之中写任何代码!是不是很酷.
置于*slide为什么不是[slide],因为它是一个结构指令.angular2规定结构指令必须使用*开头,属性指令使用[slide]进行输入.
最终效果:
1 起始页面以及下滑后 2上滑后