最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于angular實現(xiàn)模擬微信小程序swiper組件

 更新時間:2017年06月11日 09:44:13   作者:Yitim  
這篇文章主要介紹了基于angular實現(xiàn)模擬微信小程序swiper組件 ,需要的朋友可以參考下

這段時間的主業(yè)是完成一個家政類小程序,終于是過審核發(fā)布了。不得不說微信的這個小程序生態(tài)還是頗有想法的,拋開他現(xiàn)有的一些問題不說,其提供的組件系統(tǒng)乍一看還是蠻酷的。比如其提供的一個叫swiper的視圖組件,就可以在寫界面的時候省不少時間和代碼,輪播圖片跟可滑動列表都可以用。導(dǎo)致現(xiàn)在回來寫angular項目時也想整一個這樣的組件出來,本文就將使用angular的組件能力和服務(wù)能力完成這么一個比較通用,耦合度較低的swiper出來。

首先要選擇使用的技術(shù),要實現(xiàn)的是與界面打交道的東西,自然是實現(xiàn)成一個組件,最終要實現(xiàn)的效果是寫下這樣的代碼就可以完成一個可以滑動的視圖來:

<swipers>
<swiper>視圖1</swiper>
<swiper>視圖2</swiper>
</swipers>

然后要把最基本的組件定義寫出來,顯然這里要定義兩個組件。第一個是父級組件,選擇器名字就叫ytm-swipers,目前做的事情僅僅是做一個外殼定義基本樣式,使用時的子標(biāo)簽都會插入在ng-content標(biāo)簽中。

@Component({
  selector: 'ytm-swipers',
  template: `
    <div class="view-body">
      <ng-content></ng-content>
    </div>
    `,
  styles: [`
    .view-body{height: 100%;width: 100%;overflow: hidden;position: relative;}
  `]
})

第二個就是子視圖了,在父級組件下,每個子組件都會沾滿父級組件,只有當(dāng)前的子組件會顯示,當(dāng)切換視圖時實際做的就是更改這些子組件的顯示方式,說的最簡單的話,這個子組件還是僅僅用來加一個子外殼,給外殼添加基本樣式,實際的頁面內(nèi)容原封不動放在ng-content標(biāo)簽中。

@Component({
  selector: 'swiper',
  template: `
    <div class="view-child" *ngIf="swiper.displayList.indexOf(childId) >= 0"
    [ngClass]="{'active': swiper.displayList[0] === childId,
    'prev': swiper.displayList[2] === childId, 'next': swiper.displayList[1] === childId}">
      <ng-content></ng-content>
    </div>
  `,
  styles: [`
    .view-child{
      height: 100%;width: 100%;position: absolute;top: 0;
      transition: 0.5s linear;background: #fff;
      overflow-x: hidden;
    }
    .view-child.active{left: 0;z-index: 9;}
    .view-child.next{left: 100%;z-index: 7;}
    .view-child.prev{left: -100%;z-index: 8;}
  `]
})

下一步是要讓這兩個父子組件完成心靈的溝通,講道理其實可以直接使用ElementRef強行取到DOM來操作,不過這里使用的是組件內(nèi)服務(wù)。和普通的服務(wù)使用上沒差別,不過其provider是聲明在某個組件里的,所以此服務(wù)只有在此組件以及子組件中可以注入使用。

@Injectable()
class SwiperService {
  public swiperList: number[];
  public displayList: number[]; // 0為當(dāng)前 1為下一個 2為上一個
  public current: number;
  private changing: boolean;
  constructor() {
    this.changing = false;
    this.swiperList = [];
    this.displayList = [];
    this.current = 0;
  }
  public Add(id: number) {
    this.swiperList.push(id);
    switch (this.swiperList.length) {
      case 1:
        this.displayList[0] = id;
        return;
      case 2:
        this.displayList[1] = id;
        return;
      default:
        this.displayList[2] = id;
        return;
    }
  }
  public Next(): Promise<any> {
    if (this.changing) {
      return new Promise<any>((resolve, reject) => {
        return reject('on changing');
      });
    }
    this.changing = true;
    let c = this.swiperList.indexOf(this.displayList[0]);
    let n = this.swiperList.indexOf(this.displayList[1]);
    let p = this.swiperList.indexOf(this.displayList[2]);
    p = c;
    c = n;
    n = (c + 1) % this.swiperList.length;
    this.displayList[0] = this.swiperList[c];
    this.displayList[2] = this.swiperList[p];
    this.displayList[1] = -1;
    setTimeout(() => {
      this.displayList[1] = this.swiperList[n];
      this.changing = false;
    }, 500);
    return new Promise<any>((resolve, reject) => {
      return resolve(this.displayList[0]);
    });
  }
  public Prev(): Promise<any> {
    if (this.changing) {
      return new Promise<any>((resolve, reject) => {
        return reject('on changing');
      });
    }
    this.changing = true;
    let c = this.swiperList.indexOf(this.displayList[0]);
    let n = this.swiperList.indexOf(this.displayList[1]);
    let p = this.swiperList.indexOf(this.displayList[2]);
    n = c;
    c = p;
    p = p - 1 < 0 ? this.swiperList.length - 1 : p - 1;
    this.displayList[0] = this.swiperList[c];
    this.displayList[1] = this.swiperList[n];
    this.displayList[2] = -1;
    setTimeout(() => {
      this.displayList[2] = this.swiperList[p];
      this.changing = false;
    }, 500);
    return new Promise<any>((resolve, reject) => {
      return resolve(this.displayList[0]);
    });
  }
  public Skip(index: number): Promise<any> {
    let c = this.swiperList.indexOf(this.displayList[0]);
    if (this.changing || c === index) {
      return new Promise<any>((resolve, reject) => {
        reject('on changing or no change');
      });
    }
    this.changing = true;
    let n = (index + 1) % this.swiperList.length;
    let p = index - 1 < 0 ? this.swiperList.length - 1 : index - 1;
    this.displayList[0] = this.swiperList[index];
    if (index > c) {
      this.displayList[2] = this.swiperList[p];
      this.displayList[1] = -1;
      setTimeout(() => {
        this.displayList[1] = this.swiperList[n];
        this.changing = false;
      }, 500);
      return new Promise<any>((resolve, reject) => {
        return resolve(this.displayList[0]);
      });
    } else {
      this.displayList[1] = this.swiperList[n];
      this.displayList[2] = -1;
      setTimeout(() => {
        this.displayList[2] = this.swiperList[p];
        this.changing = false;
      }, 500);
      return new Promise<any>((resolve, reject) => {
        return resolve(this.displayList[0]);
      });
    }
  }
}

用到的變量包括: changing變量保證同時只能進(jìn)行一個切換,保證切換完成才能進(jìn)行下一個切換;swiperList裝填所有的視圖的id,這個id在視圖初始化的時候生成;displayList數(shù)組只會有三個成員,裝填的依次是當(dāng)前視圖在swiperList中的索引,下一個視圖的索引,上一個視圖的索引;current變量用戶指示當(dāng)前顯示的視圖的id。實際視圖中的顯示的控制就是使用ngClass指令來根據(jù)displayList和視圖id附加相應(yīng)的類,當(dāng)前視圖會正好顯示,前一視圖會在左邊剛好遮擋,后一視圖會在右邊剛好遮擋。

同時服務(wù)還要提供幾個方法:Add用于添加制定id的視圖,Next用于切換到下一個視圖(左滑時調(diào)用),Prev用于切換到前一個視圖(右滑時調(diào)用),再來一個Skip用于直接切換到指定id的視圖。

在子視圖中注入此服務(wù),需要在子視圖初始化時生成一個id并Add到視圖列表中:

export class YTMSwiperViewComponent {
    public childId: number;
    constructor(@Optional() @Host() public swiper: SwiperService) {
        this.childId = this.swip

@Injectable()
class SwiperService {
  public swiperList: number[];
  public displayList: number[]; // 0為當(dāng)前 1為下一個 2為上一個
  public current: number;
  private changing: boolean;
  constructor() {
    this.changing = false;
    this.swiperList = [];
    this.displayList = [];
    this.current = 0;
  }
  public Add(id: number) {
    this.swiperList.push(id);
    switch (this.swiperList.length) {
      case 1:
        this.displayList[0] = id;
        return;
      case 2:
        this.displayList[1] = id;
        return;
      default:
        this.displayList[2] = id;
        return;
    }
  }
  public Next(): Promise<any> {
    if (this.changing) {
      return new Promise<any>((resolve, reject) => {
        return reject('on changing');
      });
    }
    this.changing = true;
    let c = this.swiperList.indexOf(this.displayList[0]);
    let n = this.swiperList.indexOf(this.displayList[1]);
    let p = this.swiperList.indexOf(this.displayList[2]);
    p = c;
    c = n;
    n = (c + 1) % this.swiperList.length;
    this.displayList[0] = this.swiperList[c];
    this.displayList[2] = this.swiperList[p];
    this.displayList[1] = -1;
    setTimeout(() => {
      this.displayList[1] = this.swiperList[n];
      this.changing = false;
    }, 500);
    return new Promise<any>((resolve, reject) => {
      return resolve(this.displayList[0]);
    });
  }
  public Prev(): Promise<any> {
    if (this.changing) {
      return new Promise<any>((resolve, reject) => {
        return reject('on changing');
      });
    }
    this.changing = true;
    let c = this.swiperList.indexOf(this.displayList[0]);
    let n = this.swiperList.indexOf(this.displayList[1]);
    let p = this.swiperList.indexOf(this.displayList[2]);
    n = c;
    c = p;
    p = p - 1 < 0 ? this.swiperList.length - 1 : p - 1;
    this.displayList[0] = this.swiperList[c];
    this.displayList[1] = this.swiperList[n];
    this.displayList[2] = -1;
    setTimeout(() => {
      this.displayList[2] = this.swiperList[p];
      this.changing = false;
    }, 500);
    return new Promise<any>((resolve, reject) => {
      return resolve(this.displayList[0]);
    });
  }
  public Skip(index: number): Promise<any> {
    let c = this.swiperList.indexOf(this.displayList[0]);
    if (this.changing || c === index) {
      return new Promise<any>((resolve, reject) => {
        reject('on changing or no change');
      });
    }
    this.changing = true;
    let n = (index + 1) % this.swiperList.length;
    let p = index - 1 < 0 ? this.swiperList.length - 1 : index - 1;
    this.displayList[0] = this.swiperList[index];
    if (index > c) {
      this.displayList[2] = this.swiperList[p];
      this.displayList[1] = -1;
      setTimeout(() => {
        this.displayList[1] = this.swiperList[n];
        this.changing = false;
      }, 500);
      return new Promise<any>((resolve, reject) => {
        return resolve(this.displayList[0]);
      });
    } else {
      this.displayList[1] = this.swiperList[n];
      this.displayList[2] = -1;
      setTimeout(() => {
        this.displayList[2] = this.swiperList[p];
        this.changing = false;
      }, 500);
      return new Promise<any>((resolve, reject) => {
        return resolve(this.displayList[0]);
      });
    }
  }
}
er.swiperList.length;
        this.swiper.Add(this.swiper.swiperList.length);
    }
}

這個id其實就是已有列表的索引累加,且一旦有新視圖被初始化,都會添加到列表中(支持動態(tài)加入很酷,雖然不知道會有什么隱藏問題發(fā)生)。

父組件中首先必須要配置一個provider聲明服務(wù):

@Component({
  selector: 'ytm-swipers',
  template: `
    <div class="view-body">
      <ng-content></ng-content>
    </div>
    `,
  styles: [`
    .view-body{height: 100%;width: 100%;overflow: hidden;position: relative;}
  `],
  providers: [SwiperService]
})

然后就是要監(jiān)聽手勢滑動事件,做出相應(yīng)的切換。以及傳入一個current變量,每當(dāng)此變量更新時都要切換到對應(yīng)id的視圖去,實際使用效果就是:

<ytm-swipers [current]="1">...</ytm-swipers>可以將視圖切換到id喂1的視圖也就是第二個視圖。

 export class YTMSwiperComponent implements OnChanges {
  @Input() public current: number;
  @Output() public onSwiped = new EventEmitter<Object>();
  private touchStartX;
  private touchStartY;
  constructor(private swiper: SwiperService) {
    this.current = 0;
  }
  public ngOnChanges(sc: SimpleChanges) {
    if (sc.current && sc.current.previousValue !== undefined &&
    sc.current.previousValue !== sc.current.currentValue) {
      this.swiper.Skip(sc.current.currentValue).then((id) => {
        console.log(id);
        this.onSwiped.emit({current: id, bySwipe: false});
      }).catch((err) => {
        console.log(err);
      });
    }
  }
  @HostListener('touchstart', ['$event']) public onTouchStart(e) {
    this.touchStartX = e.changedTouches[0].clientX;
    this.touchStartY = e.changedTouches[0].clientY;
  }
  @HostListener('touchend', ['$event']) public onTouchEnd(e) {
    let moveX = e.changedTouches[0].clientX - this.touchStartX;
    let moveY = e.changedTouches[0].clientY - this.touchStartY;
    if (Math.abs(moveY) < Math.abs(moveX)) {
      /**
       * Y軸移動小于X軸 判定為橫向滑動
       */
      if (moveX > 50) {
        this.swiper.Prev().then((id) => {
          // this.current = id;
          this.onSwiped.emit({current: id, bySwipe: true});
        }).catch((err) => {
          console.log(err);
        });
      } else if (moveX < -50) {
        this.swiper.Next().then((id) => {
          // this.current = id;
          this.onSwiped.emit({current: id, bySwipe: true});
        }).catch((err) => {
          console.log(err);
        });
      }
    }
    this.touchStartX = this.touchStartY = -1;
  }
}

此外代碼中還添加了一個回調(diào)函數(shù),可以再視圖完成切換時執(zhí)行傳入的回調(diào),這個使用的是angular的EventEmitter能力。

以上就是全部實現(xiàn)了,實際的使用示例像這樣:

<ytm-swipers [current]="0" (onSwiped)="切換回調(diào)($event)">
   <swiper>
     視圖1
   </swiper>
   <swiper>
     視圖2
   </swiper>
   <swiper>
     視圖3
   </swiper>
 </ytm-swipers>

視圖的切換有了兩種方式,一是手勢滑動,不過沒有寫實時拖動,僅僅是判斷左右滑做出反應(yīng)罷了,二是更新[current]節(jié)點的值。

整個組件的實現(xiàn)沒有使用到angular一些比較底層的能力,僅僅是玩弄css樣式以及組件嵌套并通過服務(wù)交互,以及Input、Output與外界交互。相比之下ionic的那些組件就厲害深奧多了,筆者還有很長的路要走。

以上所述是小編給大家介紹的基于angular實現(xiàn)模擬微信小程序swiper組件,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言小編會及時回復(fù)大家的!

相關(guān)文章

  • ionic4+angular7+cordova上傳圖片功能的實例代碼

    ionic4+angular7+cordova上傳圖片功能的實例代碼

    ionic是一個垮平臺開發(fā)框架,可通過web技術(shù)開發(fā)出多平臺的應(yīng)用。這篇文章主要介紹了ionic4+angular7+cordova上傳圖片功能,本文通過實例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值 ,需要的朋友可以參考下
    2019-06-06
  • 總結(jié)AngularJS開發(fā)者最常犯的十個錯誤

    總結(jié)AngularJS開發(fā)者最常犯的十個錯誤

    AngularJS是如今最受歡迎的JS框架之一,簡化開發(fā)過程是它的目標(biāo)之一,這使得它非常適合于元型較小的apps的開發(fā),但也擴(kuò)展到具有全部特征的客戶端應(yīng)用的開發(fā)。下面給大家總結(jié)了AngularJS開發(fā)者最常犯的十個錯誤,有需要的可以參考學(xué)習(xí)下。
    2016-08-08
  • AngularJS中使用HTML5手機(jī)攝像頭拍照

    AngularJS中使用HTML5手機(jī)攝像頭拍照

    這篇文章主要介紹了AngularJS中使用HTML5手機(jī)攝像頭拍照的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • 簡介可以自動完成UI的AngularJS工具angular-smarty

    簡介可以自動完成UI的AngularJS工具angular-smarty

    這篇文章主要介紹了簡介可以自動完成UI的AngularJS工具angular-smarty,包括其中隔離作用域綁定指令符和promise的使用,需要的朋友可以參考下
    2015-06-06
  • Angular實現(xiàn)較為復(fù)雜的表格過濾,刪除功能示例

    Angular實現(xiàn)較為復(fù)雜的表格過濾,刪除功能示例

    這篇文章主要介紹了Angular實現(xiàn)較為復(fù)雜的表格過濾,刪除功能,結(jié)合實例形式分析了AngularJS針對表格的排序、查詢匹配、頁面元素屬性動態(tài)修改等相關(guān)操作技巧,需要的朋友可以參考下
    2017-12-12
  • Angular1.x復(fù)雜指令實例詳解

    Angular1.x復(fù)雜指令實例詳解

    這篇文章主要介紹了Angular1.x復(fù)雜指令,結(jié)合實例形式分析了指令的使用、模板指令、指令的作用域等概念與具體使用技巧,需要的朋友可以參考下
    2017-03-03
  • AngularJS中一般函數(shù)參數(shù)傳遞用法分析

    AngularJS中一般函數(shù)參數(shù)傳遞用法分析

    這篇文章主要介紹了AngularJS中一般函數(shù)參數(shù)傳遞用法,結(jié)合實例形式分析了模型參數(shù)與普通參數(shù)的具體功能與使用技巧,需要的朋友可以參考下
    2016-11-11
  • 詳解基于Bootstrap+angular的一個豆瓣電影app

    詳解基于Bootstrap+angular的一個豆瓣電影app

    本篇文章主要介紹了基于Bootstrap+angular的一個豆瓣電影app ,非常具有實用價值,需要的朋友可以參考下
    2017-06-06
  • angularjs指令中的compile與link函數(shù)詳解

    angularjs指令中的compile與link函數(shù)詳解

    這篇文章主要介紹了angularjs指令中的compile與link函數(shù)詳解,本文同時訴大家complie,pre-link,post-link的用法與區(qū)別等內(nèi)容,需要的朋友可以參考下
    2014-12-12
  • 探討AngularJs中ui.route的簡單應(yīng)用

    探討AngularJs中ui.route的簡單應(yīng)用

    這篇文章主要介紹了AngularJs中ui.route的簡單應(yīng)用,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-11-11

最新評論

襄汾县| 扶余县| 贞丰县| 教育| 凤凰县| 长葛市| 丽水市| 富源县| 兴业县| 阿拉尔市| 清苑县| 江城| 道孚县| 广饶县| 朝阳市| 新宾| 广元市| 庆元县| 嫩江县| 阿鲁科尔沁旗| 威信县| 保定市| 板桥市| 峡江县| 双柏县| 年辖:市辖区| 芮城县| 葫芦岛市| 商城县| 九江市| 富裕县| 台山市| 长葛市| 师宗县| 仙居县| 绍兴市| 大安市| 北川| 和林格尔县| 容城县| 城口县|