快應(yīng)用 tabs教程

2020-08-08 15:24 更新

了解如何使用tabs組件完成選項(xiàng)卡頁(yè)簽的布局,靈活組合組件,配置屬性,優(yōu)化性能

通過本節(jié),你將學(xué)會(huì):

div組件模擬選項(xiàng)卡

選項(xiàng)卡效果常見于傳統(tǒng)H5開發(fā)中,開發(fā)者一般使用div和js代碼控制布局交互得以實(shí)現(xiàn)

在框架中,開發(fā)者也可以使用div組件實(shí)現(xiàn)簡(jiǎn)單的效果,示例代碼如下:

<template>
  <div class="tutorial-page">
    <!-- div組件模擬選項(xiàng)卡功能 -->
    <div class="div-tabs">
      <!-- tabs的head部分 -->
      <div class="div-tabbar">
        <text onclick="showContent(1)">menu1</text>
        <text onclick="showContent(2)">menu2</text>
        <text onclick="showContent(3)">menu3</text>
      </div>
      <!-- tabs的body部分 -->
      <div class="div-tabcontent">
        <div class="div-tabcontent-section" show="{{type === 'content_1'}}">
          <text>content1</text>
        </div>
        <div class="div-tabcontent-section" show="{{type === 'content_2'}}">
          <text>content2</text>
        </div>
        <div class="div-tabcontent-section" show="{{type === 'content_3'}}">
          <text>content3</text>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    data: {
      type: 'content_1'
    },
    showContent (num) {
      this.type =  'content_' + num;
    }
  }
</script>

使用div組件實(shí)現(xiàn)的選項(xiàng)卡效果,功能還是有限,為了帶來最佳用戶體驗(yàn),建議使用框架提供的tabs組件完成需求

使用tabs組件

tabs中封裝了常見功能和效果:頁(yè)簽支持橫向滾動(dòng),支持手勢(shì)滑動(dòng)切換內(nèi)容頁(yè)等

tabs內(nèi)部?jī)H支持子組件tab-bartab-content,也可以只包含一個(gè)子組件,使用說明如下:

  • tab-bar組件用來包含所有頁(yè)簽的標(biāo)題,屬性mode用來配置是否可滾動(dòng),詳情請(qǐng)參考文檔:組件 -> 容器組件 -> tab-bar
  • tab-content組件用來包含所有頁(yè)簽的內(nèi)容,詳情請(qǐng)參考文檔:組件 -> 容器組件 -> tab-content
  • tab-bar組件的第n個(gè)直接子節(jié)點(diǎn)對(duì)應(yīng)tab-content中第n個(gè)直接子節(jié)點(diǎn),具有聯(lián)動(dòng)效果

示例代碼如下:

<template>
  <div class="tutorial-page">
    <!-- tabs組件 -->
    <tabs>
      <tab-bar class="tab-bar">
        <text>menu1</text>
        <text>menu2</text>
        <text>menu3</text>
      </tab-bar>
      <tab-content class="tab-content">
        <div class="tab-content-section">
          <text>content1</text>
        </div>
        <div class="tab-content-section">
          <text>content2</text>
        </div>
        <div class="tab-content-section">
          <text>content3</text>
        </div>
      </tab-content>
    </tabs>
  </div>
</template>

注意:

  • tabs內(nèi)不能再嵌套tabs,如有此類需求,請(qǐng)參考教程第一部分div組件模擬選項(xiàng)卡

頁(yè)簽內(nèi)容使用自定義子組件

為了更好的組織頁(yè)面代碼,提升代碼可維護(hù)性。開發(fā)者可以將頁(yè)簽內(nèi)容通過自定義子組件來渲染

關(guān)于如何開發(fā)子組件請(qǐng)參考文檔:父子組件通信 ,本小節(jié)僅做簡(jiǎn)單引入使用

示例代碼如下:

<import name="tab-content-item" src="./tabitem"></import>

<template>
  <div class="tutorial-page">
    <tabs onchange="onChangeTabIndex">
      <tab-bar class="tab-bar">
        <text>menu1</text>
        <text>menu2</text>
        <text>menu3</text>
      </tab-bar>
      <tab-content class="tab-content">
        <tab-content-item index="0" itemdata="{{list[0]}}" current-index="{{currentIndex}}"></tab-content-item>
        <tab-content-item index="1" itemdata="{{list[1]}}" current-index="{{currentIndex}}"></tab-content-item>
        <tab-content-item index="2" itemdata="{{list[2]}}" current-index="{{currentIndex}}"></tab-content-item>
      </tab-content>
    </tabs>
  </div>
</template>

<script>
  export default {
    data: {
      list: [
        {title: "content1"},
        {title: "content2"},
        {title: "content3"}
      ],
      currentIndex: 0
    },
    onChangeTabIndex (evt) {
      this.currentIndex = evt.index
    }
  }
</script>

tabitem.ux文件中:

<template>

  <div class="tab-section">

    <text>{{itemdata.title}}</text>

  </div>

</template>

<style>

  .tab-section {

    flex: 1;

    flex-direction: column;

    justify-content: center;

    background-color: #ffffff;

    margin: 10px;

  }

  .tab-section text {

    color: #FF0000;

    text-align: center;

  }

</style>

<script>

  export default {

    props: [

      'index',

      'itemdata',

      // 駝峰式在賦值時(shí)使用-連接

      'currentIndex'

    ],

    onInit () {

      // 監(jiān)聽屬性變化

      this.$watch('currentIndex', 'watchCurrentIndex')

    },

    /**

     * 監(jiān)聽用戶選擇的索引,選中當(dāng)前時(shí)觸發(fā)業(yè)務(wù)邏輯

     * @param newValue

     * @param oldValue

     */

    watchCurrentIndex (newValue, oldValue) {

      if (parseInt(this.index) === this.currentIndex) {

        console.info(`當(dāng)前用戶選擇了這個(gè)標(biāo)簽:${this.index}, ${newValue}, ${oldValue}`)

      }

    }

  }

</script>

頁(yè)簽內(nèi)容懶加載

一個(gè)內(nèi)容豐富的選項(xiàng)卡,通常會(huì)包含許多頁(yè)簽內(nèi)容。如新聞?lì)悜?yīng)用中,可能會(huì)包括:推薦、熱點(diǎn)、視頻、段子、汽車、社會(huì)、娛樂等

直接使用tabs默認(rèn)會(huì)加載所有頁(yè)簽內(nèi)容,導(dǎo)致JS線程持續(xù)忙于渲染每個(gè)頁(yè)簽,無(wú)法響應(yīng)用戶點(diǎn)擊事件等,造成體驗(yàn)困擾

為了解決這類問題,開發(fā)者可以讓頁(yè)簽內(nèi)容在用戶點(diǎn)擊時(shí)延遲渲染(而不是整個(gè)頁(yè)面初始化時(shí)渲染),這項(xiàng)功能可以通過if指令完成

示例代碼如下:

<template>
  <div class="tutorial-page">
    <tabs onchange="onChangeTabIndex">
      <tab-bar class="tab-bar" mode="scrollable">
        <text for="{{tabHeadList}}"  class="{{currentIndex === $idx ? 'active' : ''}}" >{{$item.title}}</text>
      </tab-bar>
      <tab-content class="tab-content">
        <div class="tab-content-section" for="{{tabHeadList}}">
          <!-- 初始化時(shí),if為false,默認(rèn)不做渲染;點(diǎn)擊后改為true -->
          <text if="{{ renderTabContent($idx) }}">{{$item.title}}</text>
        </div>
      </tab-content>
    </tabs>
  </div>
</template>

<style lang="less">

  .tutorial-page {

    flex-direction: column;

    justify-content: center;

    align-items: center;

    .tab-bar text{

      padding: 0 25px;

      text-align: center;

      font-size: 34px;

    }

    .tab-bar .active {

      color: #FF0000;

    }

    .tab-content {

      flex: 1;

      background-color: #eeeeee;

      .tab-content-section {

        flex: 1;

        margin: 10px;

        background-color: #ffffff;

        justify-content: center;

        text {

          text-align: center;

          color: #FF0000;

        }

      }

    }

  }

</style>

<script> export default { data: { tabHeadList: [ {title: "推薦"}, {title: "熱門"}, {title: "視頻"}, {title: "段子"}, {title: "汽車"}, {title: "社會(huì)"}, {title: "娛樂"}, {title: "軍事"}, {title: "體育"}, {title: "NBA"}, {title: "財(cái)經(jīng)"} ], currentIndex: 0 }, onInit(){ // 加載第一個(gè)頁(yè)簽內(nèi)容 this.changeTabIndex(0) }, changeTabIndex(index) { const item = Object.assign({}, this.tabHeadList[index]) item.render = true this.tabHeadList.splice(index, 1, item) }, onChangeTabIndex (evt) { this.currentIndex = evt.index this.changeTabIndex(evt.index) }, renderTabContent (index) { return !!this.tabHeadList[index].render } } </script>

tabs僅包含tab-content

tabs內(nèi)部可以僅包含tab-bar或者tab-content

假設(shè)開發(fā)者有如下需求:開發(fā)一個(gè)簡(jiǎn)化的社交主頁(yè),其中,用戶圖標(biāo)和搜索圖標(biāo)為跳轉(zhuǎn)按鈕,點(diǎn)擊跳轉(zhuǎn)頁(yè)面;聊天、發(fā)現(xiàn)、通訊錄為頁(yè)簽,與內(nèi)容頁(yè)聯(lián)動(dòng),效果如下:


由于tabs僅支持子組件tab-bartab-content,且tab-bartab-content的直接子元素都被當(dāng)做頁(yè)簽或內(nèi)容頁(yè)。因此,僅使用tabs無(wú)法實(shí)現(xiàn)兩個(gè)圖標(biāo)按鈕

所以開發(fā)者可以這樣實(shí)現(xiàn):

  1. tabs中,僅使用tab-content,包含選項(xiàng)卡的所有內(nèi)容頁(yè)
  2. tabs外,使用div包含選項(xiàng)卡頁(yè)簽標(biāo)題及圖標(biāo)按鈕,模擬tab-bar
  3. 在js代碼中,動(dòng)態(tài)綁定tabsindex屬性,監(jiān)聽tabschange事件,實(shí)現(xiàn)頁(yè)簽與內(nèi)容頁(yè)的聯(lián)動(dòng)

示例代碼如下:

<template>
  <div class="tutorial-page">
    <!-- 靈活使用tabs組件 -->
    <div class="flexible-tabs">
      <!-- 自定義tab-bar組件 -->
      <div class="flexible-tabbar">
        <image src="./img/user.png" onclick="routePage('personal')"></image>
        <text class="{{currentIndex === 0 ? 'active' : ''}}" onclick="clickTabBar(0)">聊天</text>
        <text class="{{currentIndex === 1 ?  'active' : ''}}" onclick="clickTabBar(1)">發(fā)現(xiàn)</text>
        <text class="{{currentIndex === 2 ? 'active' : ''}}" onclick="clickTabBar(2)">通訊錄</text>
        <image src="./img/search.png" onclick="routePage('search')"></image>
      </div>
      <!-- 監(jiān)聽change事件,觸發(fā)時(shí)動(dòng)態(tài)修改tabs的index屬性 -->
      <tabs onchange="changeTabactive" index="{{currentIndex}}">
        <tab-content class="flexible-tab-content">
          <div class="tab-content-section">
            <text>聊天</text>
          </div>
          <div class="tab-content-section">
            <text>發(fā)現(xiàn)</text>
          </div>
          <div class="tab-content-section">
            <text>通訊錄</text>
          </div>
        </tab-content>
      </tabs>
    </div>
  </div>
</template>

<style lang="less">

  .tutorial-page {

    flex: 1;

    .flexible-tabs {

      flex: 1;

      flex-direction: column;

      .flexible-tabbar {

        height: 100px;

        padding: 0 30px;

        background-color: #f1f1f1;

        align-items: center;

        text {

          flex-grow: 1;

          height: 100px;

          margin: 0 30px;

          text-align: center;

          border: 0px solid #f1f1f1;

          border-bottom-width: 5px;

        }

        image {

          height: 50px;

          width: 50px;

          resize-mode: contain;

        }

        .active {

          color: #0faeff;

          border-bottom-color: #0faeff;

        }

      }

      .flexible-tab-content {

        flex: 1;

        .tab-content-section {

          flex: 1;

          background-color: #ffffff;

          justify-content: center;

        }

      }

    }

  }

</style>

<script> import router from '@system.router' export default { data: { currentIndex: 0 }, changeTabactive (evt) { this.currentIndex = evt.index }, clickTabBar (index) { this.currentIndex = index }, routePage (param) { router.push({ uri: param }) } } </script>

總結(jié)

選項(xiàng)卡需求很常見,熟悉tabs組件的使用,有助于:提升用戶體驗(yàn)、減少加載時(shí)間、優(yōu)化頁(yè)面性能


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)