您的位置:首页 > 移动开发 > 微信开发

基于angular实现模拟微信小程序swiper组件

2017-06-09 17:30 651 查看
这段时间的主业是完成一个家政类小程序,终于是过审核发布了。不得不说微信的这个小程序生态还是颇有想法的,抛开他现有的一些问题不说,其提供的组件系统乍一看还是蛮酷的。比如其提供的一个叫swiper的视图组件,就可以在写界面的时候省不少时间和代码,轮播图片跟可滑动列表都可以用。导致现在回来写angular项目时也想整一个这样的组件出来,本文就将使用angular的组件能力和服务能力完成这么一个比较通用,耦合度较低的swiper出来。

首先要选择使用的技术,要实现的是与界面打交道的东西,自然是实现成一个组件,最终要实现的效果是写下这样的代码就可以完成一个可以滑动的视图来:

<swipers>

<swiper>视图1</swiper>

<swiper>视图2</swiper>

</swipers>

然后要把最基本的组件定义写出来,显然这里要定义两个组件。第一个是父级组件,选择器名字就叫ytm-swipers,目前做的事情仅仅是做一个外壳定义基本样式,使用时的子标签都会插入在ng-content标签中。

1 @Component({
2     selector: 'ytm-swipers',
3     template: `
4         <div class="view-body">
5             <ng-content></ng-content>
6         </div>
7         `,
8     styles: [`
9         .view-body{height: 100%;width: 100%;overflow: hidden;position: relative;}
10     `]
11 })


第二个就是子视图了,在父级组件下,每个子组件都会沾满父级组件,只有当前的子组件会显示,当切换视图时实际做的就是更改这些子组件的显示方式,说的最简单的话,这个子组件还是仅仅用来加一个子外壳,给外壳添加基本样式,实际的页面内容原封不动放在ng-content标签中。

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


下一步是要让这两个父子组件完成心灵的沟通,讲道理其实可以直接使用ElementRef强行取到DOM来操作,不过这里使用的是组件内服务。和普通的服务使用上没差别,不过其provider是声明在某个组件里的,所以此服务只有在此组件以及子组件中可以注入使用。

1 export class YTMSwiperComponent implements OnChanges {
2     @Input() public current: number;
3     @Output() public onSwiped = new EventEmitter<Object>();
4     private touchStartX;
5     private touchStartY;
6     constructor(private swiper: SwiperService) {
7         this.current = 0;
8     }
9     public ngOnChanges(sc: SimpleChanges) {
10         if (sc.current && sc.current.previousValue !== undefined &&
11         sc.current.previousValue !== sc.current.currentValue) {
12             this.swiper.Skip(sc.current.currentValue).then((id) => {
13                 console.log(id);
14                 this.onSwiped.emit({current: id, bySwipe: false});
15             }).catch((err) => {
16                 console.log(err);
17             });
18         }
19     }
20     @HostListener('touchstart', ['$event']) public onTouchStart(e) {
21         this.touchStartX = e.changedTouches[0].clientX;
22         this.touchStartY = e.changedTouches[0].clientY;
23     }
24     @HostListener('touchend', ['$event']) public onTouchEnd(e) {
25         let moveX = e.changedTouches[0].clientX - this.touchStartX;
26         let moveY = e.changedTouches[0].clientY - this.touchStartY;
27         if (Math.abs(moveY) < Math.abs(moveX)) {
28             /**
29              * Y轴移动小于X轴 判定为横向滑动
30              */
31             if (moveX > 50) {
32                 this.swiper.Prev().then((id) => {
33                     // this.current = id;
34                     this.onSwiped.emit({current: id, bySwipe: true});
35                 }).catch((err) => {
36                     console.log(err);
37                 });
38             } else if (moveX < -50) {
39                 this.swiper.Next().then((id) => {
40                     // this.current = id;
41                     this.onSwiped.emit({current: id, bySwipe: true});
42                 }).catch((err) => {
43                     console.log(err);
44                 });
45             }
46         }
47         this.touchStartX = this.touchStartY = -1;
48     }
49 }


父组件实现
此外代码中还添加了一个回调函数,可以再视图完成切换时执行传入的回调,这个使用的是angular的EventEmitter能力。

以上就是全部实现了,实际的使用示例像这样:

1 <ytm-swipers [current]="0" (onSwiped)="切换回调($event)">
2     <swiper>
3         视图1
4     </swiper>
5     <swiper>
6         视图2
7     </swiper>
8     <swiper>
9         视图3
10     </swiper>
11 </ytm-swipers>


视图的切换有了两种方式,一是手势滑动,不过没有写实时拖动,仅仅是判断左右滑做出反应罢了,二是更新[current]节点的值。

整个组件的实现没有使用到angular一些比较底层的能力,仅仅是玩弄css样式以及组件嵌套并通过服务交互,以及Input、Output与外界交互。相比之下ionic的那些组件就厉害深奥多了,笔者还有很长的路要走。

很久未写博客,原因之一是临毕业事情有点多,赚了波奖学金不亏,之二是为了写游戏一边在玩游戏一边在学DX编程,之三是懒。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: