微信小程式自定義 tabbar

来源:https://www.cnblogs.com/evenyao/archive/2018/11/29/10001970.html
-Advertisement-
Play Games

一定的需求情況下,無法使用小程式原生的 tabbar 的時候,需要自行實現一個和 tabbar 功能一模一樣的自製組件。 查閱了海量的博客和文檔之後,親自踩坑。總結了三種在不使用微信小程式原生 tabbar的情況下自製 tabbar 的方法。並說說這幾種方法各自的特色。 類 navigator 跳轉 ...


一定的需求情況下,無法使用小程式原生的 tabbar 的時候,需要自行實現一個和 tabbar 功能一模一樣的自製組件。

查閱了海量的博客和文檔之後,親自踩坑。總結了三種在不使用微信小程式原生 tabbar的情況下自製 tabbar 的方法。並說說這幾種方法各自的特色。

類 navigator 跳轉方式

類 navigator 跳轉方式是我自己起的名稱,因為它的實現思路就是這個樣子的。期初參考 微信小程式自定義tabBar組件開發 這篇博文的思路。進行了這種方式的嘗試,併為後續提供瞭解決思路。在這次實踐的過程中使用了和該博文類似的目錄結構。

 

template 文件主要包含了 tabbar 的內容、邏輯、模板、樣式。

tabbar_template.js

//初始化數據
function tabbarinit() {
  return [
    {
      "current": 0,
      "pagePath": "/pages/travel_shop/travel/travel_index/travel_index",
      "iconPath": "/pages/img/[email protected]",
      "selectedIconPath": "/pages/img/[email protected]",
      "text": "首頁"
    },
    {
      "current": 0,
      "pagePath": "/pages/travel_shop/travel/travel_car/travel_car",
      "iconPath": "/pages/img/[email protected]",
      "selectedIconPath": "/pages/img/[email protected]",
      "text": "購物車"
    },
    {
      "current": 0,
      "pagePath": "/pages/travel_shop/travel/travel_my/travel_my",
      "iconPath": "/pages/img/[email protected]",
      "selectedIconPath": "/pages/img/[email protected]",
      "text": "我的"
    }
  ]

}
//tabbar 主入口
function tabbarmain(bindName = "tabdata", id, target) {
  var that = target;
  var bindData = {};
  var otabbar = tabbarinit();
  otabbar[id]['iconPath'] = otabbar[id]['selectedIconPath']   //換當前的icon
  otabbar[id]['current'] = 1;
  bindData[bindName] = otabbar
  that.setData({ bindData });
}

module.exports = {
  tabbar: tabbarmain
}

 

 

tabbar_template.wxml

<template name="tabBar">
  <view class="tabBar">
    <block wx:for="{{tabBar}}" wx:for-item="item" wx:key="tabBar">
        <view class="tabBar-item">
            <navigator open-type="reLaunch" url="{{item.pagePath}}">
                <view><image class="tabBar-icon" src='{{item.iconPath}}'></image></view>
                <view class="{{item.current== 1 ? 'tabBartext' :''}}">{{item.text}}</view>
            </navigator>
        </view>
    </block>
 </view>
</template>

 

tabbar_template.wxss

.tabBar-icon{
  width:54rpx;
  height: 54rpx;
}
.tabBar{
  width:100%;
  position: fixed;
  bottom:0;
  padding:10rpx;
  margin-left:-4rpx;
  background:#F7F7FA;
  font-size:24rpx;
  color:#8A8A8A;
  box-shadow: 3rpx 3rpx 3rpx 3rpx #aaa; 
  z-index: 9999;
}

 .tabBar-item{
  float:left;
  width: 33.333%;
  text-align: center;
  overflow: hidden;
}
/*當前字體顏色*/
.tabBartext{
  color: black;
}
.navigator-hover{
  background-color: rgba(0, 0, 0, 0);
}

 

而後在全局引入樣式

@import "/pages/travel_shop/travel/tabbar_template/tabbar_template.wxss";

 

併在每一個頁面的子文件(wxml、JS)中引入相應的內容

wxml 引入

<import src="/pages/travel_shop/travel/tabbar_template/tabbar_template.wxml"/>
<template is="tabBar" data="{{tabBar:bindData.tabBar}}"/>

 

JS 引入

var template = require("../tabbar_template/tabbar_template.js");

併在對應的 onLoad 生命周期中,註明它是哪一個 tabbar

  onLoad: function (options) {
    template.tabbar("tabBar", 1, this) //0表示第一個tabbar,這裡1表示第二個 tabbar 的 icon
  },

 

效果預覽

 

我們最終得到了效果,但這種效果帶了明顯的抖動閃爍。原因則是因為這種實現方式的本質是通過 navigator 和 JS 事件觸發實現頁面之間的跳轉。因此我開始找尋另一種實現的方式。在 微信小程式自定義tabBar組件開發 這篇博客的留言板,我發現該文的作者也發現了這種方式的不足,並提到可以通過可以把頁面都寫成組件 component 的方式實現更好的效果。

 

template 模板 / component 組件

在繼續查閱了一些關於小程式自定義 tabbar 的博客之後,找到了 微信小程式 - 自定義tabbar 這篇博文。按照這篇博文描述的結構,我也進行了嘗試。發現這種方式不會出現之前跳轉產生的那種閃爍現象出現。

 

之後再查閱 微信小程式 template 模板與 component 組件的區別和使用 這篇博文的時候瞭解到,如果當我們主要是為了展示頁面的時候,可以使用 template 方式。如果涉及到 tabbar 對應各個頁面的業務邏輯交互比較多,那就最好使用 component 組件。

因為這三個頁面涉及到了很多獨立的交互,所以我決定使用 component 組件的形式,將自定義的 tabbar 寫成一個頁面,然後將其他三個 tabbar 按鈕對應的頁面寫成三個 component 組件。這種方法和 Vue 中的組件化很相似,可以把單個組件文件夾當成 Vue 中的一個 .vue 文件。

component 與普通 page 類似,但是 JS 文件和 JSON 文件與頁面不同。

小程式組件 JS 模板

Component({
  /* 開啟全局樣式使用 */
  options: {
    addGlobalClass: true,
  },

  /* 組件的屬性列表 */
  properties: {
    name: {
      type: String,
      value: ''
    }
  },

  /* 組件的初始數據 */
  data: {

  },

  /* 生命周期函數 */
  lifetimes: {
    attached: function () { },
    moved: function () { },
    detached: function () { },
  },

  /* 組件的方法列表 */
  methods: {

  },
})

 

component 組件 JSON 文件

{
  "component": true,
  "usingComponents": {}
}

 

tabbar 引用和配置

引用組件 JSON

按照如圖的結構,三個 component 作為子組件,tabber 作為一個父級,因此它的 JSON 需要引入這三個 component 組件。

 
// travel.json
{
  "usingComponents": {
    "travel_car": "travel_car/travel_car",
    "travel_index": "travel_index/travel_index",
    "travel_my": "travel_my/travel_my"
  }
}

 

tabbar JS

而該頁面的 JS 僅僅只用來控制 tabbar 的 icon 選擇,和傳遞一個 index 告訴頁面該隱藏和顯示哪一個 component 組件。

// travel.js
let app = getApp()

Page({
  data: {
    currentTab: 0,
    items: [
      {
        "iconPath": "/pages/img/[email protected]",
        "selectedIconPath": "/pages/img/[email protected]",
        "text": "首頁"
      },
      {
        "iconPath": "/pages/img/[email protected]",
        "selectedIconPath": "/pages/img/[email protected]",
        "text": "購物車"
      },
      {
        "iconPath": "/pages/img/[email protected]",
        "selectedIconPath": "/pages/img/[email protected]",
        "text": "我的"
      }
    ]
  },
  //事件處理函數
  bindChange: function (e) {
    let that = this;
    that.setData({
      currentTab: e.detail.current
    });
  },
  swichNav: function (e) {
    let that = this;
    if (this.data.currentTab === e.target.dataset.current) {
      return false;
    } else {
      that.setData({
        currentTab: e.target.dataset.current
      })
    }
  },
  onLoad: function () {
    let that = this
    app.getUserInfo(function (userInfo) {
      that.setData({
        userInfo: userInfo
      })
    })
  }
})

 

tabbar WXML

直接使用之前 JSON 中引用過的標簽名,類似於 Vue 中使用模板標簽。這裡由於組件模板標簽不支持直接使用 hidden 屬性,所以在外包裹了一層 view 標簽用來添加 hidden屬性。

<view hidden="{{currentTab == 0? false: true}}">
  <travel_index/>
</view>
<view hidden="{{currentTab == 1? false: true}}">
  <travel_car/> 
</view>
<view hidden="{{currentTab == 2? false: true}}">
  <travel_my/>
</view>

<view class="nav-tabs">
  <view class="tab-list {{currentTab == idx ? 'active' : 'default' }}" wx:for="{{items}}" wx:key="prototype" wx:for-index="idx" wx:for-item="item" data-current="{{idx}}" bindtap="swichNav">
    <text class="tab-text" wx:for-index="idx" data-current="{{idx}}" src="{{currentTab == idx ? item.selectedIconPath : item.iconPath }}">{{item.text}}</text>
    <image class="iconPath" wx:for-index="idx" data-current="{{idx}}" src="{{currentTab == idx ? item.selectedIconPath : item.iconPath }}"></image>
  </view>
</view>

 

tabbar WXSS

Some selectors are not allowed in component wxss, including tag name selectors, ID selectors, and attribute selectors.(./pages/xxx/xxx.wxss:288:3)This wxss file is ignored.

造成這種報錯的原因是 component 組件的樣式中不能包含一些特定的選擇器。

page {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.nav-tabs {
  width: 100%;
  display: flex;
  position: fixed;
  bottom: 0;
}

.tab-list {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column-reverse;
  background: #fcfcfc;
}

.tab-text {
  font-size: 24rpx;
  line-height: 35rpx;
  color: #5f5f5f;
}

.iconPath {
  width:54rpx;
  height: 54rpx;
}

.tab-content {
  flex: 1;
}

.default {
  line-height: 75rpx;
  text-align: center;
  flex: 1;
  color: #eee;
  font-weight: bold;
  font-size: 28rpx;
}

.active {
  line-height: 75rpx;
  text-align: center;
  color: black;
  flex: 1;
  font-weight: bold;
  font-size: 28rpx;
}

.show {
  display: block;
  flex: 1;
}

.hidden {
  display: none;
  flex: 1;
}

 

預覽效果

最終就完成了一個非原生小程式 tabbar 的自定義 tabbar 。

 

 

Github

在這篇文章發佈之後,有一些朋友詢問。 我重新整理了一個比較清晰整潔的 Demo 發佈在了 GitHub
如果這個 Demo 能夠幫助到您。請不要吝惜您的 Star

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 接上一篇,這裡使用 sequelize 來連接 postgresql 資料庫 1、安裝 sequelize,資料庫驅動 pg 2、新建配置文件夾 conf 及 配置文件 db.conf.ts 3、連接資料庫,新建文件夾 db 及 配置文件 db.ts 4、資料庫實體類,新建文件夾 models 及文 ...
  • 函數: 函數在調用的時候,會形成一個私有作用域,內部的變數不會被外面訪問,這種保護機制叫閉包。這就意味著函數調用完畢,這個函數形成的棧記憶體會被銷毀。 但有時候我們不希望他被銷毀。 函數歸屬誰跟它在哪調用沒有關係,跟在哪定義有關。 Fn()調用完畢後得到的是一個匿名函數,但是這個函數在fn這個作用域下 ...
  • 一、js判斷數組是否為空 方法一: arr.length 二、js判斷數組是否含有某個值 方法一: arr.indexOf() 方法二: for迴圈結合if判斷 方法三: arr.find(callback) ...
  • 1.解構賦值可以輕鬆獲取對象或者數組中的數據 結果: json中的數據就被輕鬆獲取; 2.解構複製可以交換變數 結果: a=4,b=3,c=2,d=1 賦值的過程需要保證兩邊的數據格式匹配 [a,b,c,d]=[d,c,b,]; d的值將為underfinded 3.對象的解構賦值 結果,666,8 ...
  • inputNumber算是一個比較簡單的組件了。 解析: (1)先看下html結構 左邊的減號和右邊的加號是通過絕對定位,設置在input左右的padding位置的,input的css代碼如下: 這個inputNumber源碼還算簡單,多看幾遍就懂了 ...
  • The web is constantly evolving. The technology was conceived and implemented based on the needs, current at the time of creation. The business require... ...
  • url的正則表達式:包括IP,功能變數名稱(domain),ftp,二級功能變數名稱,功能變數名稱中的文件,功能變數名稱加上埠!用戶名等等信息 匹配手機號 用戶名正則,4到16位(字母,數字,下劃線,減號) 密碼強度正則 整數正則 數字正則 Email正則 身份證號正則 URL正則 IPv4地址正則 十六進位顏色正則 日期正則 ...
  • 一、事件流(捕獲,冒泡) 事件流:指從頁面中接收事件的順序,有冒泡流和捕獲流。 當頁面中發生某種事件(比如滑鼠點擊,滑鼠滑過等)時,毫無疑問子元素和父元素都會接收到該事件,可具體順序是怎樣的呢?冒泡和捕獲則描述了兩種不同的順序。 DOM2級事件規定事件流包括三個階段,如圖: 假如我們點擊一個div, ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...