• quickapp_快应用_tabBar


    在这里插入图片描述
    一般首页都会显示几个tab用于进行页面切换,以下是几种tab配置方式。

    配置项中配置tabBar(版本兼容)

    manifest.json配置文件中display.tabBar可以进行tab配置,如下

    {
      "display": {
        "tabBar": {
            "color": "#000000",          //文字颜色
            "selectedColor": "#008000",        //选中文字颜色
            "tabbarBackgroundColor": "#FFFFFF",    //组件背景
             "list": [{
                "pagePath": "/home",  //页面路由路径
                "pageParams":"{test: 'test1'}" ,  //页面参数
                "iconPath": "/Common/home.png", //图标
                "selectedIconPath": "/Common/home_active.png", //选中图标
                "text": "首页"    //文字内容
              },
              {
                "pagePath": "/mine",
                "pageParams":"{test: 'test2'}",
                "iconPath": "/Common/mine.png",
                "selectedIconPath": "/Common/mine_active.png",
                "text": "我的"
              }]
          }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    但是此时存在以下两个问题

    • [1] tabBar配置项是在1110+版本适用,在低于1110版本中不起作用。
      (目前绝大部分机型版本为1070+),还有很多手机型号不兼容!
    • [2] tab不能动态配置!

    使用tabs组件配置tabBar

    语法
    • 概括

      tabs组件:仅支持最多一个tab-bar组件和最多一个tab-content组件。

      tab-bar组件: tabs的标签展示区,子组件排列方式为横向排列

      tab-content组件:tabs的内容展示区,高度默认充满 tabs 剩余空间,子组件排列方式为横向排列

    • 说明
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

    示例
    
    <import name="library" src="../../components/library">import>
    
    <import name="bookshelf" src="../../components/bookshelf">import>
    
    <import name="ranking" src="../../components/bookshelf/ranking.ux">import>
    
    <import name="mine" src="../../components/mine">import>
    
    <template>
    <div class="page-wrapper">
      
      <tabs index="{{selectedTab}}" onchange="changeTab" >
        <tab-content>
          <library>library>
          <bookshelf id='bookshelf'>bookshelf>
          <ranking >ranking>
          <mine>mine>
        tab-content>
        <tab-bar mode="fixed" class="tab-bar">
          <div class="tab-item" for="tabList">
            <image class="iconfont" src='{{ selectedTab === $idx ? $item.onfocus_icon_url : $item.icon_url}}'>image>
            <text class="tab-title">{{ $item.title }}text>
          div>
        tab-bar>
      tabs>
    div>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    <script>
    export default {
      private: {
        tabList: [],
        selectedTab: 0 //默认第一个页面
      },
      onInit() {
        this.init()
      },
      init (){
        this.tabList = [
          {
            title: '书城',
            icon_url: 'https://img.iwave.net.cn/other/c7d4037ba99fea69c46dc096f46b11b6.png',
            onfocus_icon_url: 'https://img.iwave.net.cn/other/c996112028a8de365b292d7fcc95ebc2.png',
            type: 0
          },
          {
            title: '书架',
            icon_url: 'https://img.iwave.net.cn/other/6862b4ec95abc6f6f40494f67a6fae0d.png',
            onfocus_icon_url: 'https://img.iwave.net.cn/other/23512e7e0b47bbaf0d2a86f7dfb1c986.png',
            type: 1
          },
          {
            title: '排行榜',
            icon_url: 'https://img.iwave.net.cn/other/64f89f4184c04f20143c49c0685659c1.png',
            onfocus_icon_url: 'https://img.iwave.net.cn/other/d5b9e41090cdbbc1d92dae91f2d4398b.png',
            type: 2
          },
          {
            title: '我的',
            icon_url: 'https://img.iwave.net.cn/other/f6e7f3684b50f041f00e88c0753466c0.png',
            onfocus_icon_url: 'https://img.iwave.net.cn/other/2e72f98dc9780b08cd00f684f2ca2c21.png',
            type: 3
          }
        ]
      },
      changeTab(e) {
        let index = e.index === undefined ? 1 : e.index
        this.selectedTab = index
      }
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    问题-切换tab没有反应

    最初我是直接将tabList写死的,这样tab切换没有问题

    init(){
    this.tabList = [...]
    }
    
    • 1
    • 2
    • 3

    后来进行动态配置,从后端获取数据,发现tab切换没有反应

    init(){
      const res = await $http.httpGet('init')
      if (res && !res.status) {
        this.tabList = res.data.tabs
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这是为什么呢?

    原因是因为tab组件的子组件tab-bar、tab-content中的数据是不允许动态变换的!

    若是动态加载需要在加载完成时再渲染,也就是加上if判断

    <tabs index="{{selectedTab}}" onchange="changeTab" if='tabList.length'>
      ...
    </tabs>
    
    • 1
    • 2
    • 3
    问题-数据渲染问题

    知识点: 自定义组件生命周期+ 父子组件生命周期执行顺序

    前提:以上示例中的四个组件(书城、书架、排行榜、我的)的初始化都是在init生命周期执行的。

    问题1:当打开示例中的页面时会同时初始化这四个组件(打开页面时走4个组件的init生命周期函数)。

    思考:我就在想要不在页面展现的时候再初始化呢(show生命周期中),经过实践发现自定义组件没有show生命周期。

    问题2: 再次打开书城、书架、排行榜、我的页面时存在不更新数据的情况。

    原因:[1] 切换tab的时候都是在main页面,不会执行任何生命周期; [2]在主页去其他页面点击左上角返回时走的是main组件的show生命周期,子组件不执行任何生命周期。因此除了通过router跳转到首页外,子组件只初始化一次!

    解决

    tips: 如果数据量不是很大的话,可以接受在初始化的时候同时初始化4个页面!

    若是介意同时加载

    • [1]自定义组件中:不在init生命周期中进行初始化,封装一个init方法进行初始化
      init(){
        // 初始化
      }
      
      • 1
      • 2
      • 3
    • [2] 主页中:在ready生命周期默认初始化第一个组件
      onReady(){
        this.$child('library').init()
      }
      
      • 1
      • 2
      • 3
      每次展示页面和切换tab时加载对应组件
      onShow(){
        this.refreshBookShelf()
      },
      changeTab(e) {
        let index = e.index === undefined ? 1 : e.index
        this.selectedTab = index
        this.refreshBookShelf()
      },
      refreshBookShelf(){
        if (this.selectedTab == 0) {
          this.$child('library').init()
        }
        if (this.selectedTab == 1) {
          this.$child('bookshelf').init()
        }
        if (this.selectedTab == 2) {
          this.$child('ranking').init()
        }
        if (this.selectedTab == 3) {
          this.$child('mine').init()
        }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
    优化

    在这个需求里面书城、排行榜、我的页面的数据不是经常更新,

    所以我在main页面打开时同时初始化四个页面

    在切换tab或者是展示main页面时只重新加载书架的内容(因为书架内容会根据用户行为实时变化)

    另外在书城、排行榜、我的页面添加下拉刷新(若是用户想要更新数据可以通过下拉刷新去更新)

    • [1] 组件:在init生命周期中进行初始化,封装一个init方法进行初始化
      onInit(){
        this.init()
      },
      init(){
        // 初始化
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • [2] 主页:由于书架数据需要每次打开页面都更新
      onShow(){
        this.refreshBookShelf()
      },
      changeTab(e) {
        let index = e.index === undefined ? 1 : e.index
        this.selectedTab = index
        this.refreshBookShelf()
      },
      refreshBookShelf(){
        if (this.selectedTab == 1) {
          this.$child('bookshelf').init()
        }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
    问题-tab的动态配置

    现在的tab虽然tab-bar中的数据可以动态配置(动态显示tab名字和icon),但是对应的组件是固定的。
    在这里插入图片描述
    此时可以通过循环判断的方式进行

    通过tab-bar配置的type固定是哪个组件进行渲染

    <block for='item in tabList'>
      <library if='item.type == 0'>library>
      <bookshelf if='item.type == 1' id='bookshelf'>bookshelf>
      <ranking if='item.type == 2'>ranking>
      <mine if='item.type == 3'>mine>
    block>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意只能通过if判断是否展示组件!!!!使用三元表达式和&&判断不起效果!!!!

    <block for='item in tabList'>
      {{
        (
          item.type == 0 ? <library></library> : (
          item.type == 1 ? <bookshelf id='bookshelf'></bookshelf> : (
          item.type == 2 ? <ranking></ranking> : <mine></mine>
        )))
      }}
    </block>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    此时会在tab-content中渲染16个组件!!!
    在这里插入图片描述
    相当于是不管判断成不成立,每次循环都渲染4个组件!!!

    另外就是其他页面跳转到main页面时传递的selectedTab值必须与type对应!

    比如跳转到排行版页面

    const index = this.tabList.findIndex(item => item.type == 2)
    router.push('/page/main',{
      selectedTab: index
    })
    
    • 1
    • 2
    • 3
    • 4

    第三方组件tabbar

    直接使用第三方组件库的tabbar组件

  • 相关阅读:
    国内饮料行业数据浅析
    深兰科技成功入选《2023年度国家知识产权优势企业名单》
    十七、k8s-helm-初探
    【vscode远程开发】使用内网穿透实现在公网环境下远程访问
    公众号网页开发 - 本地开发环境中将公众号授权域名使用内网穿透(frp+nginx)进行本地开发、调试
    代码随想录算法训练营第四十九天 | 121. 买卖股票的最佳时机 & ​122. 买卖股票的最佳时机 II​
    软件行业里测试与质量保证的区别
    小米手机抓取hci log
    Open3D ICP精配准(使用鲁棒性核函数)
    个保法(PIPL)颁布实施一周年,给行业带来了哪些变化?
  • 原文地址:https://blog.csdn.net/qq_43260366/article/details/134459778