【Taro】【微信小程序】在Taro中自定義custom導航欄TabBar時狀態無法更新問題


 

最近小程序有一個新的需求,那就是對底部的TabBar進行各種的大小顏色等控制,沒辦法,默認的TabBar已經不夠打了,只能查文檔看看怎么自定義,果然是可以自定義的,小程序文檔:https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html

而且,文檔還貼心的給出了示例代碼,https://developers.weixin.qq.com/s/jiSARvmF7i55 ,點擊就可以用微信的開發者工具打開,nice!原來是在src目錄下新增一個custom-tab-bar的文件夾,同時在全局的配置文件中配置一下就可以了,哦呦,還挺簡單的嘛,可是心里總感覺很虛,因為以我之前開發時對Taro尿性的了解,保不齊就出點什么小毛病

對示例着照貓畫虎,總算是跑起來了,底部的tabbar也顯示出來了,但是果然發現問題了!在頁面DidShow時用Taro無法拿到TabBar的示例,進而無法刷新TabBar,切換TabBar時,顏色不會跟着改變,或者改變的是錯的!

開始網上大量查找解決辦法,https://www.jianshu.com/p/ec016dec7f9c ,最后借鑒了這篇文章的做法把問題解決了,我是通過Redux對tab的index狀態進行管理,從而使得切換正常的,但是第一次切換的時候,仍然有一點閃爍,不過只能先忍了,下班了,如果有人看的話,有時間把代碼整理整理貼上來,嘿嘿溜了溜了~

----------------------------------------------------------------------------------------------------------------------------------------------------

我來整理啦!

首先是主要結構:

- src
  - custom-tab-bar
    - index.jsx
    - index.scss
  - reducer
    - index.js
    - tabbar.js
  - store
    - index.js
  - pages
    - index
      - index.jsx
    - me
      - index.jsx
- app.config.js

代碼:

1. src/custom-tab-bar/index.jsx
tabbar的主要文件,這里基本和小程序文檔給的示例一致,主要區別在於引入的狀態管理Redux,代碼上區別在最后export的時候有一個connect寫法。然后還要注意這里使用的是CoverView和CoverImage,這樣Tabbar基本一直在最上方,就算打開手機的調試模式,vconsole那個按鈕都會被蓋住。。。,這里有需要的可以替換成View和Image,靈活控制層級~
 1 import React, {Component} from 'react'
 2 import Taro from '@tarojs/taro'
 3 import {CoverView, CoverImage} from '@tarojs/components'
 4 
 5 import {connect} from 'react-redux'
 6 
 7 import './index.scss'
 8 
 9 class CustomTabBar extends Component {
10   tabInfo = {
11     color: '#7A7E83',
12     selectedColor: '#149EFF',
13     list: [
14       {
15         pagePath: '/pages/index/index',
16         text: '首頁',
17         iconPath: '../asset/common/nav_index_normal.png',
18         selectedIconPath: '../asset/common/nav_index_selected.png',
19       },
20       {
21         pagePath: '/pages/me/index',
22         text: '我的',
23         iconPath: '../asset/common/nav_my_normal.png',
24         selectedIconPath: '../asset/common/nav_my_selected.png',
25       },
26     ],
27   }
28 
29   switchTab = (e) => {
30     const data = e.currentTarget.dataset
31     Taro.switchTab({
32       url: data.path,
33     })
34   }
35 
36   render() {
37     console.log('render', this.props.tabbar)
38     const activeTab = this.props.tabbar.index
39     return (
40       <CoverView class="tab-bar">
41         <CoverView class="tab-bar-border"></CoverView>
42         {this.tabInfo.list.map((item, index) => (
43           <CoverView
44             class="tab-bar-item"
45             data-path={item.pagePath}
46             data-index={index}
47             onClick={(e) => this.switchTab(e)}
48             key={item.text}
49           >
50             <CoverImage
51               src={activeTab === index ? item.selectedIconPath : item.iconPath}
52             ></CoverImage>
53             <CoverView
54               style={`color: ${
55                 activeTab === index
56                   ? this.tabInfo.selectedColor
57                   : this.tabInfo.color
58               }`}
59             >
60               {item.text}
61             </CoverView>
62           </CoverView>
63         ))}
64       </CoverView>
65     )
66   }
67 }
68 
69 export default connect(({tabbar}) => ({
70   tabbar,
71 }))(CustomTabBar)

 

2. src/custom-tab-bar/index.scss
tabbar的樣式,可以根據需求自定義哦~
.tab-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: 54Px;
  background: white;
  display: flex;
  padding-bottom: env(safe-area-inset-bottom);
}

.tab-bar-border {
  background-color: #F3F4F9;
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 1Px;
  transform: scaleY(0.5);
}

.tab-bar-item {
  flex: 1;
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}

.tab-bar-item cover-image {
  width: 33Px;
  height: 33Px;
}

.tab-bar-item cover-view {
  font-size: 11Px;
}

3. src/reducer/index.js
Redux的相關文件,主要是對當前的index進行一個全局的管理,以便在改變時讓tabbar刷新,因為我也是現學現賣就不多說明了,大家可以去Redux的官網看使用方法或者去這里Taro文檔
import {combineReducers} from 'redux'
import tabbar from './tabbar'

export default combineReducers({
  tabbar,
})

4. src/reducer/tabbar.js
Redux的相關文件
const SETACTIVETAB = 'SETACTIVETAB'

export const setActiveTab = (idx) => {
  return {
    type: SETACTIVETAB,
    meta: {idx},
  }
}

const INITIAL_STATE = {
  index: 0,
}

export default function tabbarReducer(state = INITIAL_STATE, action) {
  switch (action.type) {
    case SETACTIVETAB:
      return {
        ...state,
        index: action.meta.idx,
      }
    default:
      return state
  }
}

5. src/store/index.js
依然是Redux的相關文件
import {createStore, applyMiddleware, compose} from 'redux'
import thunkMiddleware from 'redux-thunk'
import rootReducer from '../reducers'

const composeEnhancers =
  typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
    ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
    : compose

const middlewares = [thunkMiddleware]

// if (
//   process.env.NODE_ENV === 'development' &&
//   process.env.TARO_ENV !== 'quickapp'
// ) {
//   middlewares.push(require('redux-logger').createLogger())
// }

const enhancer = composeEnhancers(
  applyMiddleware(...middlewares)
  // other store enhancers if any
)

export default function configStore() {
  const store = createStore(rootReducer, enhancer)
  return store
}

 

6. src/pages/index/index.js
差不多弄完了,接下來這兩個就是我們tabbar所要導航到的兩個頁面,在DidShow生命周期更新全局變量index,這樣Redux就會去刷新Tabbar的狀態
...
import {connect} from 'react-redux'
import {setActiveTab} from '../../reducers/tabbar'

class Index extends Component {
  ...
  componentDidShow() {
    this.props.dispatch(setActiveTab(0))
  }
  ...
  render() {
      ...      
  }      
}

export default connect()(Index)

 

7. src/pages/me/index.js
...
import {connect} from 'react-redux'
import {setActiveTab} from '../../reducers/tabbar'

class Me extends Component {
  ...
  componentDidShow() {
    this.props.dispatch(setActiveTab(1))
  }
  ...
  render() {
      ...      
  }      
}

export default connect()(Me)

 

8. src/app.config.js
偶對,別忘了全局配置文件中的改動,OK,完事兒
export default {
    ...

    tabBar: {
        custom: true,
        backgroundColor: '#fff',
        selectedColor: '#149EFF',
        list: [
          {
            pagePath: 'pages/index/index',
            text: '首頁',
            iconPath: 'asset/common/nav_index_normal.png',
            selectedIconPath: 'asset/common/nav_index_selected.png',
          },
          {
            pagePath: 'pages/me/index',
            text: '我的',
            iconPath: 'asset/common/nav_my_normal.png',
            selectedIconPath: 'asset/common/nav_my_selected.png',
          },
        ],
      },

      usingComponents: {},
}

 

總結一下,主要坑的點在於微信原生可以在對應導航的頁面中拿到Tabbar的實例,來setData
this.getTabBar().setData({
     selected: 1
})

可是Taro中你得這么干

this.$scope.getTabBar().$component.setState({
   ... 
})

但是你卻發現


心里一頓mmp之后還是抱有一絲希望的使用getCurrentInstance().page,並把它的返回結果打印出來,但是怎么找也找不到實例的setState或者可以改變狀態的可行辦法(好像里面有個setData,但是不管用?),然后就¥%&¥&……*…………*¥
 
啊好了,好消息總算是可以解決這個問題了,不得不說小程序坑是真的多,Taro也是,我好苦啊~~嗚嗚,有時間再寫一些其他的坑,好了,該休息了,晚安了 



如果這篇文章幫到你,記得留言讓我知道哦,讓我知道我不是一個人,如果有更好的解決辦法或者錯誤也請不吝賜教,溜了溜了

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM