沙汀 發表於 2022-5-6 10:14:00

UNI-APP 自定义微信小程序底部导航栏

<p>本文只针对于微信小程序的自定义底部导航栏;<br>
<strong>PS</strong>:可能在进入小程序后,首次点击tabBar会出现闪烁的情况;不能接受的就还是乖乖的用回默认吧!</p>
<h2 id="需求">需求</h2>
<p>在开发记账APP时,感觉微信小程序默认的tabBar功能很简单,而且不能进行美化,作为强迫症的我,不能忍,直接搂它;<br>
我需要达到的效果如下:</p>
<ul>
<li>中间的按钮凸起;</li>
<li>中间的按钮点击时需要跳转二级页面;</li>
</ul>
<p><img src="https://img2022.cnblogs.com/blog/1667295/202205/1667295-20220506101242478-1967635946.png" alt="" loading="lazy"></p>
<h2 id="方案">方案</h2>
<p>当然,我们以UNI-APP官方的案例为主,先看一下官方怎么做的:UNI-APP 自定义 tabBar;<br>
官方文档也是描述了一下,具体实现也还是需要使用wxml、wxss进行实现,并且需要将自定义tabBar放在项目根目录下的custom-tab-bar文件夹下;最终方案也是跳到了微信社区:微信小程序 自定义 tabBar;</p>
<h2 id="实现">实现</h2>
<h3 id="1修改配置pagejson文件">1、修改配置page.json文件</h3>
<p>添加custom字段,并赋值true,表示这里我们使用的是自定义的tabBar;<br>
此时,我们这里的配置数据就不生效了;<br>
<img src="https://img2022.cnblogs.com/blog/1667295/202205/1667295-20220506101258715-2134690294.png" alt="" loading="lazy"></p>
<h3 id="2添加自定义tabbar">2、添加自定义tabBar</h3>
<h4 id="a创建文件夹">a、创建文件夹</h4>
<p>文件包含自定义tabBar:index.js、index.json、index.wxml、index.wxss</p>
<p><img src="https://img2022.cnblogs.com/blog/1667295/202205/1667295-20220506101311143-2079774788.png" alt="" loading="lazy"></p>
<p>针对我上述图中的效果,代码如下:</p>
<h5 id="indexjs">index.js</h5>
<pre><code class="language-javascript">Component({
data: {
    selected: 0,
    color: "#D1D1D1",
    selectedColor: "#A6B1E1",
    list: [{
      "pagePath": "/pages/index/index",
      "text": "账目"
    },
    {
      "pagePath": "/pages/profile/index",
      "text": "我的"
    }]
},
attached() {
},
methods: {
    switchTab(e) {
      const data = e.currentTarget.dataset
      const url = data.path
      wx.switchTab({ url })
      this.setData({
      selected: data.index,
      })
    },
    // 此处需要针对中间的tabBar跳转到二级页面,而不是使用switchTab
    toadd() {
      wx.navigateTo({ url: '/pages/bill/edit' })
    }
}
})
</code></pre>
<h5 id="indexjson">index.json</h5>
<pre><code class="language-json">{
"component": true
}
</code></pre>
<h5 id="indexwxml">index.wxml</h5>
<pre><code class="language-html">&lt;!--miniprogram/custom-tab-bar/index.wxml--&gt;
&lt;view class="tab-bar"&gt;
&lt;view wx:for="{{list}}" wx:key="index" class="tab-bar-item {{item.bulge?'bulge':''}}" data-path="{{item.pagePath}}" data-index="{{index}}" bindtap="switchTab"&gt;
    &lt;viewwx:if="item.bulge" class="tab-bar-bulge tab-bar-view"&gt;&lt;/view&gt;
    &lt;image style="display: {{item.bulge? 'block' : 'none'}};" class="image" src="{{selected === index ? item.selectedIconPath : item.iconPath}}"&gt;&lt;/image&gt;
    &lt;viewwx:if="{{item.text}}" style="color: {{selected === index ? selectedColor : color}}" class="tab-bar-view"&gt;{{item.text}}&lt;/view&gt;
&lt;/view&gt;
&lt;view class="bulge"bindtap="toadd"&gt;
    &lt;view class="background"&gt;
      &lt;image class="image" src="/static/assets/tabbar/plus.png"&gt;&lt;/image&gt;
    &lt;/view&gt;
&lt;/view&gt;
&lt;/view&gt;
</code></pre>
<h5 id="indexwxss">index.wxss</h5>
<pre><code class="language-css">.tab-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 48px;
display: flex;
line-height: 1.2;
padding-bottom: env(safe-area-inset-bottom);
background: white;

}

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

.bulge {
position: absolute;
left: 50%;
right: 50%;
transform: translate(-50%);
top: -12px;
height: 80px;
width: 60px;
display: flex;
justify-content: center;
}

.bulge .background{
background: #A6B1E1;
width: 45px;
height: 45px;
border-radius: 100%;
display: flex;
justify-content: center;
align-items: center;
}

.bulge .background .image{
width: 20px;
height: 20px;
}

.tab-bar-item .tab-bar-view {
font-size: 13px;
font-weight: bold;
}
</code></pre>
<h3 id="3修改tabbar指向页面">3、修改tabBar指向页面</h3>
<p>实际开发中,如果不进行此项处理则会导致点击tabBar时出现奇怪的问题:点击另外一个bar时,上一个bar才会处于被选中状态;</p>
<p>解决该问题就要在每个tabBar指向页面的onShow添加如下代码:<br>
<strong>PS:网上很多教程都是使用<code>this.$mp.getTabBar</code> 或<code>this.$root.$mp.getTabBar</code>去实现(</strong>uni-app v2.0.0之前应该没事<strong>),但会在热重载tab page时都会报错:<code>Error in onShow hook: "TypeError: Cannot read property 'getTabBar' of undefined"</code>,如下图:</strong><br>
<img src="https://cdn.nlark.com/yuque/0/2022/png/1589422/1651659545257-9672e5d0-cdf0-4487-bee6-62a33daaced8.png#crop=0&amp;crop=0&amp;crop=1&amp;crop=1&amp;from=url&amp;id=sSUr5&amp;margin=%5Bobject%20Object%5D&amp;originHeight=250&amp;originWidth=969&amp;originalType=binary&amp;ratio=1&amp;rotation=0&amp;showTitle=false&amp;status=done&amp;style=none&amp;title=" alt="" loading="lazy"><br>
经过一番issue折腾后,最终使用如下实现:</p>
<pre><code class="language-javascript">onShow() {
    // 网上很多教程都是使用this.$mp.getTabBar 或 this.$root.$mp.getTabBar去实现
    // 但目前的uni-app(2.0.1)版本下会出现undefined的情况,官方的解决方案是使用如下方式
    if (typeof this.$scope.getTabBar === 'function' &amp;&amp;
      this.$scope.getTabBar()) {
      this.$scope.getTabBar().setData({
            // 当前页面对应的tab index
            selected: 0,
      })
    }
}
</code></pre>
<p>但是,我们需要优雅点,使用mixins进行混入,达到一个function随处使用,且本文使用的时局部混入,需要在使用到的页面进行混入,代码如下:</p>
<h5 id="构建mixins">构建mixins</h5>
<p>根目录下创建mixins文件夹,并创建tabbar.js</p>
<pre><code class="language-javascript">export const mixin = {
    methods: {
      setTabBarIndex(index) {
            if (typeof this.$scope.getTabBar === 'function' &amp;&amp;
                this.$scope.getTabBar()) {
                this.$scope.getTabBar().setData({
                  selected: index,
                })
            }
      }
    }
}
</code></pre>
<h5 id="在需要混入的页面进行配置">在需要混入的页面进行配置</h5>
<pre><code class="language-javascript">// 引入混入js
import { mixin } from "@/mixins/tabbar.js";

export default {
mixins: , //混入js文件
onShow() {
    this.setTabBarIndex(0);
},
}
</code></pre>
<h3 id="需要注意">需要注意</h3>
<ul>
<li>在UNI-APP编译后,生成了dist文件夹后再进行此项更改,且直接热更新使用的话会出现两个tabBar且重叠的情况,此时需要删除dist,并重新生成;</li>
</ul><br><br>
来源:https://www.cnblogs.com/memoyu/p/16227592.html
頁: [1]
查看完整版本: UNI-APP 自定义微信小程序底部导航栏