美文网首页hybrid APP(ionic)Ionic3项目实战教程ionic开发
ionic3项目实战教程 - 第10讲 ionic3分类菜单设计

ionic3项目实战教程 - 第10讲 ionic3分类菜单设计

作者: IonicBlog | 来源:发表于2017-08-24 21:43 被阅读1906次

    注意,干货来了,相比前面几讲这一讲就要难以消化多了,请做好心理准备。

    因为在这之前,经常看到有群友在求这种分类菜单的组建,今天我就为大家再造一个轮子 [微笑脸]。

    这一讲主要包含以下几个部分:

    • 1.效果图
    • 2.布局思考
    • 3.具体代码展示

    1.效果图

    10-1.png

    2.布局思考

    • 2.1.左右布局,考虑用ion-grid,一个ion-row,两个ion-col;

        <ion-grid>
          <ion-row>
             <ion-col>这里放菜单列表</ion-col>
             <ion-col>这里放商品列表</ion-col>
          </ion-row>
        </ion-grid>
      
    • 2.2.分类和商品列表需要滚动

        <ion-grid>
          <ion-row>
             <ion-col><ion-scroll>这里放菜单列表</ion-scroll><ion-col>
             <ion-col><ion-scroll>这里放商品列表</ion-scroll><ion-col>
          </ion-row>
        </ion-grid>
      
    • 2.3.左边菜单使用ion-list,右边商品列表使用我们之前封装的组建ion-products

    3.具体代码展示

    这一讲的所有改动都在/src/pages/contact文件夹中,相信通过前面的几讲,大家对ionic3已经有了一个�初步的认识,那么读懂以下代码应该不是难事。

    以下分别是 contact.module.ts ,contact.ts, contact.html , contact.scss 的完整代码:

    这里用到了ion-products组建,需要在对应的module中导入依赖:

    contact.module.ts

    import { ComponentsModule } from './../../components/components.module';
    import { NgModule } from '@angular/core';
    import { IonicPageModule } from 'ionic-angular';
    import { ContactPage } from './contact';
    
    @NgModule({
        declarations: [
            ContactPage,
        ],
        imports: [
            IonicPageModule.forChild(ContactPage),ComponentsModule
        ],
    })
    export class ContactPageModule { }
    

    难读懂的代码都添加了注释。

    contact.ts

    import { AppGlobal, AppService } from './../../app/app.service';
    import { Component, ViewChild } from '@angular/core';
    import { NavController, IonicPage } from 'ionic-angular';
    
    @IonicPage()
    @Component({
      selector: 'page-contact',
      templateUrl: 'contact.html'
    })
    export class ContactPage {
    
      @ViewChild('scroll') scrollElement: any;
      @ViewChild('spinner') spinnerElement: any;
    
      categories: Array<any> = [];
      selectedMenuTarget: any;
      products: Array<any> = [];
      hasmore = true;
    
      islock = false;
    
      params = {
        favoritesId: 0,
        pageNo: 1
      }
    
      constructor(public navCtrl: NavController,
        public appService: AppService) {
    
      }
    
      ionViewDidLoad() {
        this.getCategories();
        this.addScrollEventListener();
      }
    
      addScrollEventListener() {
        this.scrollElement._scrollContent.nativeElement.onscroll = event => {
          if (this.spinnerElement) {
            //元素顶端到可见区域顶端的距离
            var top = this.spinnerElement.nativeElement.getBoundingClientRect().top;
            //可见区域高度
            var clientHeight = document.documentElement.clientHeight;
            if (top <= clientHeight) {
              console.log("ready loadmore...");
              this.doInfinite();
            }
          }
        }
      }
    
      // 获取左侧菜单
      getCategories() {
        this.appService.httpGet(AppGlobal.API.getCategories, { appTag: 'dress' }, rs => {
          console.debug(rs);
          this.categories = rs.data;
          //默认获取第一个分类的商品列表
          this.params.favoritesId = this.categories[0].FavoritesId;
          this.getProducts();
        })
      }
    
      // 选中左侧菜单
      itemClick(c, event) {
    
        var initSelected: any = document.getElementsByClassName('menuItem');
        if (initSelected[0].classList.contains("active")) {
          initSelected[0].classList.remove("active")
        }
    
        //移除上次选中菜单的样式
        if (this.selectedMenuTarget) {
          this.selectedMenuTarget.classList.remove("active")
        }
    
        //修改本次选中菜单的样式
        event.currentTarget.classList.add("active");
    
        //将本次选中的菜单记录
        this.selectedMenuTarget = event.currentTarget;
    
        this.hasmore = true;
    
        this.params.favoritesId = c.FavoritesId;
        this.params.pageNo = 1;
    
        this.getProducts();
      }
    
      getProducts() {
        this.appService.httpGet(AppGlobal.API.getProducts, this.params, rs => {
          this.products = rs.data;
          this.params.pageNo += 1;
        })
      }
    
      doInfinite() {
        if (this.islock) {
          return;
        }
        if (this.hasmore == false) {
          return;
        }
        this.islock = true;
        this.appService.httpGet(AppGlobal.API.getProducts, this.params, d => {
          this.islock = false;
          if (d.data.length > 0) {
            this.products = this.products.concat(d.data);
            this.params.pageNo += 1;
          } else {
            this.hasmore = false;
            console.log("没有数据啦!")
          }
        });
      }
    
      goDetails(item) {
        this.navCtrl.push('ProductDetailsPage', { item: item });
      }
    }
    

    这里说明下,addScrollEventListener函数里主要实现的是自定义加载更多功能。

    contact.html

    <ion-header>
      <ion-navbar style="opacity: 0.8" no-border-bottom color="primary">
        <ion-title>优惠精选</ion-title>
      </ion-navbar>
    </ion-header>
    <ion-content fullscreen>
      <ion-grid no-padding>
        <ion-row>
          <ion-col col-3 class="menus">
            <ion-scroll scrollY="true" style="height:100%">
              <ion-list no-lines>
                <ion-item button class="menuItem" *ngFor="let c of categories;let i=index" [ngClass]="{'active': i==0}" text-center (click)="itemClick(c,$event)">
                  {{c.FavoritesTitle}} </ion-item>
              </ion-list>
            </ion-scroll>
          </ion-col>
          <ion-col class="items">
            <ion-scroll scrollY="true" #scroll style="height:100%">
              <ion-products [products]="products"></ion-products>
              <ion-row>
                <ion-col class="nodata" text-center *ngIf="!hasmore">
                  没有商品啦 ♪(^∇^*)
                </ion-col>
              </ion-row>
              <ion-row #spinner *ngIf="hasmore">
                <ion-col text-center>
                  <ion-spinner></ion-spinner>
                </ion-col>
              </ion-row>
            </ion-scroll>
          </ion-col>
        </ion-row>
      </ion-grid>
    </ion-content>
    

    contact.scss

      page-contact {
      background: #efefef;
      .menus {
        height: 100%;
        ion-scroll {
          background-color: #efefef;
        }
      }
      .items {
        height: 100%;
        ion-scroll {
          background-color: #fff;
        }
      }
      ion-grid {
        padding: 0px;
        margin: 0px;
        height: 100%;
        ion-row {
          padding: 0px;
          margin: 0px;
          height: 100%;
          ion-col {
            padding: 0px;
            margin: 0px;
          }
        }
      }
      ion-list {
        ion-item {
          background: #efefef;
        }
      }
      .product {
        .scroll-content {
          margin-bottom: 0px;
        }
      }
      .menus {
        .active {
          background: #fff;
        }
        ion-item {
          background: #efefef;
          ion-label {
            font-family: "黑体";
            font-size: 90%;
          }
        }
      }
    }
    

    如果有不理解的地方,欢迎大家在文章下方进行留言,也可通过文章下方的联系方式联系到我。

    完!

    相关文章

      网友评论

      • 寂寞_0837:楼主大神,请问一下this.scrollElement._scrollContent.nativeElement.onscroll = event => {
        console.log(this.scroll2._scrollContent.nativeElement.scrollLeft);
        }这个方法只能监听一个滚动的div,如果我想一个页面分别监听两个以上滚动的div,该怎么写呀
      • 73b4989b97a0:如何显示网络请求的数据?
        例如:
        <div>
        <div>{{cj_title}}</div>
        <div>{{cj_content}}</div>
        </div>

        我如何在网络请求数据之后给cj_title赋值?我直接写this.cj_title=rs.title是没有反应的
      • 472d249dcf89:楼主,_scrollContent 这个编译不过,提示找不到这个属性,是什么原因。如果这个用ionic3自己的上拉加载,加载完成后,加载那个区域又不消息,不知道怎么弄了
        472d249dcf89:@小新吃烧饼 能够给一份完整代码参考一下,191866599@qq.com
        472d249dcf89:@IonicBlog 直接就是编译报错,找不到_scrollContent这个元素
        IonicBlog:console.log(this.scrollElement);
        打印一下我看看
      • 十八掌:请问一下 appService 这个是干嘛的了 怎么没见它的了
        IonicBlog:@十八掌 github搜索ionic3-dress
        十八掌:@IonicBlog 可以贴一份代码吗 楼主
        IonicBlog:@十八掌 全局的网络请求服务
      • 杭州朱亚文:为什么不用ionic3自带的上拉加载商品呢。???是性能不好吗?
      • d2709b874723:出现错误:
        Class 'Subject<T>' incorrectly extends base class 'Observable<T>'. Types of property 'lift' are incompatible. Type '<R>(operator: Operator<T, R>) => Observable<T>' is not assignable to type '<R>(operator: Operator<T, R>) => Observable<R>'. Type 'Observable<T>' is not assignable to type 'Observable<R>'. Type 'T' is not assignable to type 'R'.
        请问这该怎么解决?谢谢
        简单就好_fbba:@佑写情 我界面出不来,是不是接口关了
        佑写情:1.找到tsconfig.json文件
        2.添加noStrictGenericChecks。
        {
        "compilerOptions": {
        "noStrictGenericChecks": true
        }
        }
        709217c562e4:这个问题解决了吗?
      • Spon9e:楼主您好,此节2.1和2.2布局思考中,
        <ion-col>这里放菜单列表<ion-col>
        <ion-col>这里放商品列表<ion-col>
        关闭标签忘记了 /
        正确:
        <ion-col>这里放菜单列表</ion-col>
        <ion-col>这里放商品列表</ion-col>
        :blush:
        IonicBlog:@Spon9e 多谢纠正
      • dml1874:@ViewChild('scroll') scrollElement: any和ionViewDidLoad()函数,它们的主要作用是什么,可以讲解一下吗?在官网看教程的时候,没太注意它们的用法
      • 雪之音:教程真棒,刚好要学ionic3
      • 7cf8c8a251e9: var top = this.spinnerElement.nativeElement.getBoundingClientRect().top; 这是获取的什么高度啊,this.spinnerElement.nativeElement.getBoundingClientRect() 这个语法是哪里的e
        IonicBlog:当前元素顶端到可见区域顶端的距离,教程中是有注释的

      本文标题:ionic3项目实战教程 - 第10讲 ionic3分类菜单设计

      本文链接:https://www.haomeiwen.com/subject/ldntdxtx.html