用ionic做一個仿京東商品詳情頁的過程記錄

之前只有一個詳情頁,老闆說改成和京東一樣的0.o

效果圖

在這裏插入圖片描述

1.導航欄 ionic2-super-tabs

原本打算導航用“ionic2-super-tabs”做,但是這個super-tabs是一個整體 ,tab和內容頁連在一起, 不能同時滿足在tab上加東西和讓內容頁佔滿屏幕。

<ion-row style="height:100%;background:#fff;">
  <ion-col col-3>
    
  </ion-col>
  <ion-col col-6 no-padding>
    <super-tabs *ngIf="categoryList.length>0" id="storeTabs" [config]="{ sideMenu: 'left' }">
      <super-tab *ngFor="let item of categoryList;" [root]="item.page" [title]="item.titel" id="item.id"></super-tab>
    </super-tabs>
  </ion-col>
  <ion-col col-3>
    2 3
  </ion-col>
</ion-row>

在這裏插入圖片描述
調起來有點麻煩,這個有空再看怎麼改。

2.導航欄 <ion-segment>

於是改用另外一個ionic的組件<ion-segment>

<ion-header>
  <ion-navbar>
        <ion-segment [(ngModel)]="detailtype">
          <ion-segment-button value="detailgoods">
            商品
          </ion-segment-button>
          <ion-segment-button value="detailinfo">
            詳情
          </ion-segment-button>
          <ion-segment-button value="detailevaluate">
            評價
          </ion-segment-button>
          <ion-segment-button value="detailrecommend">
            推薦
          </ion-segment-button>
        </ion-segment>
      
      <ion-buttons end>
        <button ion-button>
          <i class="iconfont iconfont_small icon-fenxiang1 list-item-ic"></i>
        </button>
        <button ion-button>
          <i class="iconfont iconfont_small icon-more list-item-ic"></i>
        </button>
      </ion-buttons>
  </ion-navbar>
</ion-header>

<ion-content> 
  <div [ngSwitch]="detailtype">
    <ng-container *ngSwitchCase="'detailgoods'">
      detailgoods
    </ng-container>

    <ng-container *ngSwitchCase="'detailinfo'">
      詳情
    </ng-container>

    <ng-container *ngSwitchCase="'detailevaluate'">
      評價
    </ng-container>

    <ng-container *ngSwitchCase="'detailrecommend'">
      推薦
    </ng-container>
  </div>
</ion-content>

然後效果是
2018121203.png
然後再重寫一下<ion-segment>的樣式。

3.單個segment的頁面處理

<ion-nav>導航(可能影響了後邊的滑動,待解決)

<ion-content> 
  <div [ngSwitch]="detailtype">
    <ng-container *ngSwitchCase="'detailgoods'" >
      <ion-nav [root]="DetailgoodsPage" [rootParams]="rootParams"></ion-nav>
    </ng-container>

    <ng-container *ngSwitchCase="'detailinfo'">
      <ion-nav [root]="DetailinfoPage" [rootParams]="goodsdetail"></ion-nav>
    </ng-container>

    <ng-container *ngSwitchCase="'detailevaluate'">
      <ion-nav [root]="DetailevaluatePage"></ion-nav>
    </ng-container>

    <ng-container *ngSwitchCase="'detailrecommend'">
      <ion-nav [root]="DetailrecommendPage" [rootParams]="role"></ion-nav>
    </ng-container>
  </div>
</ion-content>
4.頁面跳轉問題

遇到一個頁面跳轉的問題:
在這裏插入圖片描述
在這裏插入圖片描述
產生的原因
推薦這個segment內是一個商品列表,push進去後也是和當前一樣的商品詳情頁,但是是在segment內跳轉的,所以頁面會嵌在segment內
解決:從當前segment的父級push

gotodetail(brand) {
    //this.navCtrl.push('GoodsdetailPage',{goods_id: brand.goods_id,role: this.role});
    this.navCtrl.parent.push('GoodsdetailPage',{goods_id: brand.goods_id,role: this.role});
  }

參考官方文檔:NavController的實例成員parent

5. 商品頁滑上去,導航欄漸變的效果

外層<ion-content>的ionScroll沒有效果,可能是因爲嵌入了<ion-segment>的原因,所以滾動的是ion-segment內的頁面,觸發的也是ion-segmention-content的scroll事件;

於是去掉了第3步的導航,將四個sgement的內容都拿出來放到當前頁面,這樣的話第4步也不必了;

漸變效果分析

  1. 一開始在商品頁導航欄透明度是0,頁面滾動時透明度漸變,頭部內的內容也隨着變化,往上滾動到一定距離會變成固定值
  2. 切換到其它頁時,透明度一直是那個固定值不會變化;
  3. 切回到商品頁時,透明度還是之前在商品頁時的透明度。

導航欄變化時機:1.商品頁滑動時2.切換segment頁面時。
實現

  1. 設置3個全局的變量
//導航欄
scrolltop: any;//商品頁上滑的高度
opacity: any;//透明度
headerheight: any;//header高度
  1. 商品頁綁定scroll事件,得到往上滾動的距離,計算透明度值,改變導航欄樣式
scrollToTop(evt) {
    if(this.detailtype=="detailgoods") {
      console.log('detailgoods_scrollToTop');
      console.log(evt);
      this.scrolltop = evt.scrollTop;
      this.opacity = this.scrolltop/this.headerheight;
      this.updatestyle('detailgoods');
    }
  }
  1. 切換segment時改變導航欄樣式

這裏計算margin-top原本是設置給外層的但是設置不了,才設置在了裏一層的div,效果一樣

  segmentChanged(evt) {
    //margin高度
    //
    if(evt.value=="detailgoods") {
      this.renderer.setStyle(this.goodsdetailContent.nativeElement,'margin-top','0');
    }else {
      this.renderer.setStyle(this.goodsdetailContent.nativeElement,'margin-top',String.raw`${this.headerheight}px`);
    }

    //導航欄
    this.updatestyle(evt.value);
  }
  1. 根據透明度改變導航欄的樣式

這裏在取被點擊的那個segment時總是取不到,最先用的是直接取包含.segment-activated的dom元素,但是一直取的都是上一次點擊的segment,明明那個狀態已經改變了;後來改成在被點擊的大segment裏取包含.segment-activated的dom元素,和上種情況一樣;然後根據當前被點擊的那個segment-button終於取到了當前被點擊的segment,但是沒有nativeElement不能操作dom;於是繼續採用第一種方法,不過加了個定時器延遲了取dom的時間終於取到了對的,但是加了一個有固定時間的定時器不太好。
於是求助了頭兒後的最終的方法是,給每個segment加固定的id,切換時取當前id的dom元素就可以了,不用管什麼.segment-activated啦!(感覺自已好死腦筋,有變化的class不好取,取id不就行了?0.o)
在這裏插入圖片描述
在這裏插入圖片描述

//更新導航欄樣式
  updatestyle(detailtype) {
    //segment按鈕
    let objel = this.element.nativeElement.querySelectorAll('.segment-button');
    // let objelact = this.element.nativeElement.querySelectorAll('.segment-activated')[0];
    let objelact = this.element.nativeElement.querySelectorAll('#'+detailtype)[0];

    //兩邊按鈕
    let headerbtn = this.element.nativeElement.querySelectorAll('ion-header .bar-button-ios');
    //右邊的按鈕
    let rightbtn = this.element.nativeElement.querySelectorAll('.endbtn .bar-button-ios');
    //左邊的按鈕
    let leftbtn = this.element.nativeElement.querySelectorAll('.back-button .button-inner')[0];

    if(detailtype=="detailgoods") {
      // console.log(true);
      if(this.opacity>=0.9) {
        this.opacity = 0.9;
        headerbtn.forEach((element)=>{
          this.renderer.setStyle(element,'color',String.raw`rgba(136,136,136, 1)`);
        })
        rightbtn.forEach((element)=>{
          this.renderer.setStyle(element,'background',String.raw`rgba(136,136,136, 0)`);
        })
        this.renderer.setStyle(leftbtn,'background',String.raw`rgba(136,136,136, 0)`);
      }else if(this.opacity>=0.3 && this.opacity<1){
        headerbtn.forEach((element)=>{
          this.renderer.setStyle(element,'color',String.raw`rgba(136,136,136, ${this.opacity})`);
        })
        rightbtn.forEach((element)=>{
          this.renderer.setStyle(element,'background',String.raw`rgba(136,136,136, 0`);
        })
        this.renderer.setStyle(leftbtn,'background',String.raw`rgba(136,136,136, 0`);
      }else {
        headerbtn.forEach((element)=>{
          this.renderer.setStyle(element,'color',String.raw`rgba(255, 255, 255, ${1-this.opacity})`);
        })
        rightbtn.forEach((element)=>{
          this.renderer.setStyle(element,'background',String.raw`rgba(136,136,136, ${0.3-this.opacity})`);
        })
        this.renderer.setStyle(leftbtn,'background',String.raw`rgba(136,136,136, ${0.3-this.opacity})`);
        
      }

      objel.forEach((element)=>{
        this.renderer.setStyle(element,'color',String.raw`rgba(136,136,136, ${this.opacity})`);
      })
      this.renderer.setStyle(objelact,'color',String.raw`rgba(211, 71, 44, ${this.opacity})`);
      this.renderer.setStyle(objelact,'border-color',String.raw`rgba(211, 71, 44, ${this.opacity})`);
     
      //header背景
      this.renderer.setStyle(this.goodsheader.nativeElement,'background',String.raw`rgba(255, 255, 255, ${this.opacity})`);
    }else {
      // console.log(false);
      objel.forEach((element)=>{
        this.renderer.setStyle(element,'color',String.raw`rgba(136,136,136, 1)`);
      })
      this.renderer.setStyle(objelact,'color',String.raw`rgba(211, 71, 44, 1)`);
      this.renderer.setStyle(objelact,'border-color',String.raw`rgba(211, 71, 44, 1)`);

      //header背景
      this.renderer.setStyle(this.goodsheader.nativeElement,'background',String.raw`rgba(255, 255, 255, 1)`);
      headerbtn.forEach((element)=>{
        this.renderer.setStyle(element,'color',String.raw`rgba(136,136,136, 1)`);
        
      })
      rightbtn.forEach((element)=>{
        this.renderer.setStyle(element,'background',String.raw`rgba((136,136,136, 0)`);
      })
      this.renderer.setStyle(leftbtn,'background',String.raw`rgba((136,136,136, 0)`);
    }
  }
  1. html:
<ion-header #goodsheader no-border>
  <ion-navbar class="seachr-panel">
    <ion-segment (ionChange)="segmentChanged($event)" [(ngModel)]="detailtype">
      <ion-segment-button id="detailgoods" value="detailgoods">
        商品
      </ion-segment-button>
      <ion-segment-button id="detailinfo" value="detailinfo">
        詳情
      </ion-segment-button>
      <ion-segment-button id="detailevaluate" value="detailevaluate">
        評價
      </ion-segment-button>
      <ion-segment-button id="detailrecommend" value="detailrecommend">                         
        推薦
      </ion-segment-button>
    </ion-segment>

    <ion-buttons class="endbtn" end>
      <button ion-button>
        <i class="iconfont icon-fenxiang1 list-item-ic"></i>
      </button>
      <button ion-button>
        <i class="iconfont icon-more list-item-ic"></i>
      </button>
    </ion-buttons>
  </ion-navbar>
</ion-header>


<ion-content (ionScroll)="scrollToTop($event)">
  <div #goodsdetailContent [ngSwitch]="detailtype">
    <ng-container *ngSwitchCase="'detailgoods'">
    	...
    </ng-container>
    <ng-container *ngSwitchCase="'detailinfo'">
    	...
    </ng-container>
    <ng-container *ngSwitchCase="'detailevaluate'">
    	...
    </ng-container>
    <ng-container *ngSwitchCase="'detailrecommend'">
    	...
    </ng-container>
   </div>
</ion-content>

效果:

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章