美文网首页
一步一步使用Vue写一个简单的顶部Tabbar

一步一步使用Vue写一个简单的顶部Tabbar

作者: 流水_事 | 来源:发表于2019-08-11 16:08 被阅读0次

最近用Hybird写一些简单的需求。其中有一个要用到顶部选项卡的控件。在github上并没有找到合适的,要么过于复杂,要么样式不合适。于是决定自己写一个简单的顶部选项卡。这篇文章是分享做这个tabbar的过程以及其中遇到的一些问题。

使用到的知识点

vue 的组件,绑定,事件传递,css的动态绑定

先来看我们要做成的原页面(原生iOS做的):


屏幕快照 2019-08-11 下午3.04.28.png

要做的组件就是顶部的tabbar这一块。

分析

其实就是要放n个tab view布满整个宽度,然后底部要一个滑动条可以动画滚动。

关键问题点:

  1. tabs数组是作为属性传递过来的,如果按照百分比来定义宽度,如何动态地把css中的宽度跟传递的data做绑定?
  2. 点击tabbar后,如何让底部的滑动条滚动到合适的位置?

步骤

由于对vue和css还不是特别熟悉,这里采取分步的方式一点一点达到最终的效果。

  1. 将整个tabbar作为一个view而不是一个组件。先做好整个view再抽取一个单独的组件出来。 这样做相对于一开始就把它当做一个组件来说,少了引用与传值的部分,对于初学不久的人来说最好是控制变量,保证问题集中在自己关注的地方。

  2. 写死数据,先固定宽度25%写死,先把整体的界面先完成。完成简单的数据绑定,避开第一个难点。
    此时的代码

<template>
    <view class="container">
        <view class="tab-container">
            <view class="tabs">
                <view class="tab-item"
                 v-for="(item,index) in tabNames"
                 style="width:25%">
                    <text class="tab-label">{{item}}</text>
                </view>
            </view>
            <view class="slider"  ref="slider"></view>
        </view>
    </view>
</template>
<script>
    export default {
        data() {
            return {
                tabNames: ["代办","已办","待阅","已阅"]
            }
        }
    }
</script>

  1. 开始研究第一个问题,如何动态地绑定tab的宽度,使其能够刚好布满整个屏幕的宽度。没有太多的技术深度,这里直接贴出来:
:style="{width: (100/tabNames.length) + '%'}"

这里主要注意一下语法的问题就可以了。

  1. 绑定点击事件,处理底部滑块的位置。在这里因为对css动画的不熟悉,我也分了两步。第一,先达到没有动画移动滑动位置的效果,只需要修改margin-left属性就可以了。但是需要在js的事件函数中去获取滑块的css属性来修改:
                let style = this.$refs.slider.$el.style;
                let offset = 25*index + '%';
                style['margin-left'] = offset;
  1. 达到效果以后,改为用动画让滑块平滑地移动。查阅css动画即可
                let style = this.$refs.slider.$el.style;
                let offset = 100*index + '%';
                //字符串模板的使用 ${}
                style['transform'] = `translate(${offset})`;

这里要注意的点是元素在translate百分比移动的时候,是已自身的宽度为单位的,所以要把offset的基准定为100%

  1. 开始抽离tabbar作为一个单独的控件,这时候要考虑作为一个组件,有哪些地方是应该由外部传入而作为属性存在的。
    由于是个简单的demo,这里只把最基础的配置抽出来:tabs的数据源,是否显示底部的滑块,点击事件的传递($emit)
    此时组件的代码如下:
<template>
    <view class="tab-container">
        <view class="tabs">
            <view 
             class="tab-item"
             v-for="(item,index) in tabNames"
             :style="{width: (100/tabNames.length) + '%'}"
             @click="onTabClick(index)">
                <text 
                class="tab-label"
                :class="selectedIndex===index?'selected':''"
                >{{item}}</text>
            </view>
        </view>
        <view class="slider" ref="slider" v-if="showSlider"></view>
    </view>
</template>

<script>
    export default {
        name: "top-tab-bar",
        props: {
            tabNames: Array,
            showSlider: Boolean
        },
        data() {
            return {
                selectedIndex: 0    
            }
        },
        methods: {
            onTabClick(index) {
                // 获取slider的style
                this.$data.selectedIndex = index;
                let slider = this.$refs.slider;
                if (slider !== undefined) {
                    let style = slider.$el.style;
                    let offset = 100*index + '%';
                    //字符串模板的使用 ${}
                    style['transform'] = `translate(${offset})`;
                }
                this.$emit('onTabClick',index);
            }
        }
    }
</script>

这里遇到的一个小坑就是在绑定的时候如果用到v-for里面的item时,需要将绑定的代码写在在v-for以后(也就是item定义以后)

点击的tab的样式的绑定:

:class="selectedIndex===index?'selected':''"
  1. 在父组件中使用:
<template>
    <view class="container">
        <top-tab-bar 
        :tabNames="tabNames"
        :showSlider="true"
        @onTabClick="onTabClick">
        </top-tab-bar>
    </view>
</template>

<script>
    import TopTabBar from "./top-tab-bar.vue"
    export default {
        components: {
            TopTabBar
        },
        data() {
            return {
                tabNames: ["代办","已办","待阅","已阅"]
            }
        },
        methods: {
            onTabClick(index) {
                console.log("parent receive on tab click! ");
            }
        }
    }
</script>
  1. 最后。提供完整的使用。通过tabbar切换显示的数据源
<template>
    <view class="container">
        <top-tab-bar 
        :tabNames="tabNames"
        :showSlider="true"
        @onTabClick="onTabClick">
        </top-tab-bar>
        <message-list class="list" :messages="currentMessages"></message-list>
    </view>
</template>

<script>
    import TopTabBar from "./top-tab-bar.vue"
    import messageData from "./message-data.js"
    import MessageList from "./message-list.vue"
    
    export default {
        components: {
            TopTabBar,
            MessageList
        },
        data() {
            return {
                tabNames: ["代办","已办","待阅","已阅"],
                messages: [messageData.todo, messageData.done, messageData.unread, messageData.readed],
                currentMessages: messageData.todo
            }
        },
        methods: {
            onTabClick(index) {
                console.log("parent receive on tab click! ");
                this.$data.currentMessages = this.$data.messages[index];
            }
        }
    }
</script>

最终效果 具体的小样式就没有详细完善了

屏幕快照 2019-08-11 下午3.04.16.png

接下来的目标:

  1. 将tab从tabbar中抽离出来,单独定义tab的样式,可以有图片或者角标
  2. tabbar可以滑动,类似头条的顶部分类tabbar
  3. 和scrollview相结合,tabbar提供随着底部页面的滑动而滑动的功能

相关文章

  • 一步一步使用Vue写一个简单的顶部Tabbar

    最近用Hybird写一些简单的需求。其中有一个要用到顶部选项卡的控件。在github上并没有找到合适的,要么过于复...

  • day04 Vue.js初步学习

    一、了解Vue.js 简单小巧的渐进式技术栈,可以一步一步、有阶段性地来使用Vue.js,不必一开始就使用所有的东...

  • 2019-03-06

    1 Vue.js是什么:简单小巧的渐进式技术栈,可以一步一步、有阶段性地来使用Vue.js,不必一开始就使用所有的...

  • 1 Vue.js起步

    1 Vue.js是什么 简单小巧的渐进式技术栈,可以一步一步、有阶段性地来使用Vue.js,不必一开始就使用所有的...

  • Vue-cli搭建项目

    第一步 vue-cli vue-cli安装非常简单,它为我们节省了很多webpack配置文件。vue-cli的使用...

  • 六、Flutter自定义Tabbar

    目录一、效果展示二、底部Tabbar三、顶部Tabbar 一、效果展示 底部Tabbar切换和顶部Tabbar切换...

  • QML 实现App通用tabBar

    QML tabBar 默认是Material 风格,默认只能顶部Tab 使用,象常用软件底部tabBar 风格.需...

  • 揭开vue神秘面纱之v-model

    带你一步一步走进vue之实现一个简单的v-model About 源码aboutmegithubblog 1,实现...

  • 搭建基于webpack的vue项目

    简单搭建基于webpack环境下的Vue项目,在此过程中熟悉webpack以及vue的简单用法,按照步骤一步一步进...

  • Flutter携程App旅拍页面

    目录 顶部TabBar + TabBarView 瀑布流照片墙 图片加载策略 顶部TabBar + TabBarV...

网友评论

      本文标题:一步一步使用Vue写一个简单的顶部Tabbar

      本文链接:https://www.haomeiwen.com/subject/ktcsjctx.html